准确计算时间差

简单地使用 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

你可能感兴趣的:(时间)