惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
B
Blog RSS Feed
C
Check Point Blog
D
Docker
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
MongoDB | Blog
MongoDB | Blog
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
量子位
有赞技术团队
有赞技术团队
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
M
MIT News - Artificial intelligence
B
Blog
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
月光博客
月光博客

博客园 - 文's sky

泛型列表(List)的搜索和排序 [笔记]读取含日期格式的记录SQLite报错"该字符串未被识别为有效的 DateTime"的问题 FtpWebRequest 的杂症 - "The server committed a protocol violation","基础连接已经关闭: 服务器提交了协议冲突" SqlServer 2000默认开启连接池 设计模式学习系列-C#的单件模式 ASP 整合ASP.NET的URL参数编码问题 - 文's sky 序列化遇到"不应有的节点" 转换链接的正则 一、NVelocity介绍 NVelocity开篇 EXPLORER自动连接221.5.250.163 ASP.NET C# 验证码 支持中文 噪点 弯曲 模板机制的第一个程序Hello World [笔记]DataView格式化显示数据不能的问题 .Net论坛,让人看笑话~ 实在受不了了,大家来帮帮我如何调用这个C++/CLI的DLL C#外挂专用截取显示器图像代码 C#游戏外挂代码 重置递增号
准确计算时间差
文's sky · 2007-12-06 · via 博客园 - 文's sky

简单地使用 beginDate - endDate 不精确,总是某个值的倍数,比如 0.015625 秒的倍数,值比较小时,干脆就是个0 (0 倍)。

.NET Framework v2.0 中新增了一个 System.Diagnostics.Stopwatch 对象,本文就是说用它来计算时间差,.NET 2.0 中是现成的,因此对 2.0 来说,这文章没什么意义,只要知道有这个对象就可以了,用法也相当简单,举例:

public void SomeMethod()
{
    Stopwatch stopwatch 
= Stopwatch.StartNew();
    
// do something 
    
// 仅仅简单举例, Stopwatch 还提供了其他更为详细的属性和方法。
    Console.WriteLine("Elapsed Seconds: {0}", stopwatch.Elapsed.TotalSeconds);
}

在 1.1 里没有提供,但只需把该对象完整的反编译代码 Copy 出来自建一个 Stopwatch 对象,再做一点小改动就 OK 了。 代码与举例:

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;namespace Zealot.Framework.Web.Utils
{
    
/// <summary>
    
/// v1.1 没有 Stopwatch,从 v2.0 复制出来
    
/// </summary>
    public class Stopwatch
    {
        
// Fields
        private long elapsed;
        
public static readonly long Frequency;
        
public static readonly bool IsHighResolution;
        
private bool isRunning;
        
private long startTimeStamp;
        
private static readonly double tickFrequency;
        
private const long TicksPerMillisecond = 0x2710;
        
private const long TicksPerSecond = 0x989680;// Methods
        static Stopwatch()
        {
            
if (!SafeNativeMethods.QueryPerformanceFrequency(out Frequency))
            {
                IsHighResolution 
= false;
                Frequency 
= 0x989680;
                tickFrequency 
= 1;
            }
            
else
            {
                IsHighResolution 
= true;
                tickFrequency 
= 10000000;
                tickFrequency 
/= (double)Frequency;
            }
        }
public Stopwatch()
        {
            
this.Reset();
        }
private long GetElapsedDateTimeTicks()
        {
            
long rawElapsedTicks = this.GetRawElapsedTicks();
            
if (IsHighResolution)
            {
                
double num2 = rawElapsedTicks;
                num2 
*= tickFrequency;
                
return (long)num2;
            }
            
return rawElapsedTicks;
        }
private long GetRawElapsedTicks()
        {
            
long elapsed = this.elapsed;
            
if (this.isRunning)
            {
                
long num3 = GetTimestamp() - this.startTimeStamp;
                elapsed 
+= num3;
            }
            
return elapsed;
        }
public static long GetTimestamp()
        {
            
if (IsHighResolution)
            {
                
long num = 0;
                SafeNativeMethods.QueryPerformanceCounter(
out num);
                
return num;
            }
            
return DateTime.UtcNow.Ticks;
        }
public void Reset()
        {
            
this.elapsed = 0;
            
this.isRunning = false;
            
this.startTimeStamp = 0;
        }
public void Start()
        {
            
if (!this.isRunning)
            {
                
this.startTimeStamp = GetTimestamp();
                
this.isRunning = true;
            }
        }
public static Stopwatch StartNew()
        {
            Stopwatch stopwatch 
= new Stopwatch();
            stopwatch.Start();
            
return stopwatch;
        }
public void Stop()
        {
            
if (this.isRunning)
            {
                
long num2 = GetTimestamp() - this.startTimeStamp;
                
this.elapsed += num2;
                
this.isRunning = false;
            }
        }
// Properties
        public TimeSpan Elapsed
        {
            
get
            {
                
return new TimeSpan(this.GetElapsedDateTimeTicks());
            }
        }
public long ElapsedMilliseconds
        {
            
get
            {
                
return (this.GetElapsedDateTimeTicks() / ((long)0x2710));
            }
        }
public long ElapsedTicks
        {
            
get
            {
                
return this.GetRawElapsedTicks();
            }
        }
public bool IsRunning
        {
            
get
            {
                
return this.isRunning;
            }
        }
    }
}

编译时发现有 2 处错误,无法找到 SafeNativeMethods 对象,因为它是 internal 访问限制的。 而 在这个类里用到了 SafeNativeMethods 中的两个方法,QueryPerformanceFrequency 和 QueryPerformanceCounter,把他们也反编译出来,直接加入自建的 Stopwatch 类当中,或者在与 Stopwatch 相同的命名空间下同样自建一个 SafeNativeMethods 类就可以了。

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;namespace Zealot.Framework.Web.Utils
{
    [SuppressUnmanagedCodeSecurity]
    
internal class SafeNativeMethods
    {
        [DllImport(
"kernel32.dll")]
        
internal static extern bool QueryPerformanceCounter(out long value);

        [DllImport(

"kernel32.dll")]
        
internal static extern bool QueryPerformanceFrequency(out long value);
    }
}

转自:http://www.zealotforce.net/reply-638.aspx