.net平臺下獲取高精度時間類

原文:http://www.it118.org/specials/321869dd-98cb-431b-b6d2-82d973cd739d/d940a15c-0d36-4369-8de0-b07cf3f3fd5f.htmweb

 

 

前言:.NET 2.0前運行庫中不存在高精度的計時器,而您又須要它,解決的方法是經過調用QueryPerformanceFrequency  QueryPerformanceCounter這兩個Win32 API來實現。在.NET 2.0時,stopwatch類也可實現高精度計時,請參考:《使用Stopwatch類實現高精度計時工具

.NET運行庫具備一個屬性—— System.Environment.Tickcount,您可使用它計算時間。該屬性返回計算機最近一次啓動以後,已用時間滴答數(ms)。一開始,您可能以爲它是一個很是好的工具。可是,它有一個至關顯著的缺陷,即該屬性並非每毫秒都更新。

該屬性的更新頻率一般依賴於計時器的分辨率。在該案例中,tick-count屬性的分辨率是15 ms。若是您在一個循環中持續訪問該屬性,則在更新以前的每15ms它返回相同的值,而後在下一次更新以前的另外一個15ms中,它返回一個新的值。現代的計算機每秒可以執行很是巨大的計算量,15ms的分辨率將使得您的計算看上去好像「停停動動的」。

警告:

若是但願在應用程序中使用TickCount屬性,那麼必須明確它返回的是一個無符號整數值。由於該屬性是計算機啓動以後已用時間的滴答數,因此若是計算機運行了很是長的時間 (例如超過25天),該屬性將返回一個負數。若是您沒有考慮這種狀況,將使得正在使用的公式出錯。在更長的一段時間以後,該值將從新歸0。

這裏您須要的是一個具備更高分辨率的計時器。一個分辨率爲1ms的計時器是您很是好的選擇。this

.NET 2.0前運行庫中不存在高精度的計時器,而您又須要它,解決的方法是經過調用QueryPerformanceFrequency  QueryPerformanceCounter這兩個Win32 API來實現。spa

  1. using System;  
  2. using System.Runtime.InteropServices;  
  3.   
  4. internal sealed class AccurateTimerHelper  
  5. {  
  6.     public AccurateTimerHelper()  
  7.     {  
  8.         TicksPerSecond = this.GetTicksPerSecond();  
  9.         this.BaseTime = this.GetTime();  
  10.     }  
  11.   
  12.     [DllImport("kernel32.dll", EntryPoint="QueryPerformanceCounter")]  
  13.     private static extern int QueryPerformanceCounter(ref long lpPerformanceCount);  
  14.     [DllImport("kernel32.dll", EntryPoint="QueryPerformanceFrequency")]  
  15.     private static extern int QueryPerformanceFrequency(ref long A_0);  
  16.   
  17.   
  18.     public long GetElapsedTime()  
  19.     {  
  20.         return (long)((((double)(this.GetTime() - this.BaseTime)) / ((double)TicksPerSecond)) * 10000);  
  21.     }  
  22.   
  23.     private long GetTime()  
  24.     {  
  25.         long time = 0;  
  26.         if (AccurateTimerHelper.QueryPerformanceCounter(ref time) == 0)  
  27.         {  
  28.             throw new NotSupportedException("Error while querying the high-resolution performance counter.");  
  29.         }  
  30.         return time;  
  31.     }  
  32.   
  33.     private long GetTicksPerSecond()  
  34.     {  
  35.         long ticksPerSecond = 0;  
  36.         if (AccurateTimerHelper.QueryPerformanceFrequency(ref ticksPerSecond) == 0)  
  37.         {  
  38.             throw new NotSupportedException("Error while querying the performance counter frequency.");  
  39.         }  
  40.         return ticksPerSecond;  
  41.     }  
  42.       
  43.   
  44.     private long BaseTime  
  45.     {  
  46.         get  
  47.         {  
  48.             return baseTime;              
  49.         }  
  50.         set  
  51.         {  
  52.             this.baseTime = value;   
  53.         }  
  54.     }  
  55.   
  56.     private long TicksPerSecond  
  57.     {  
  58.         get  
  59.         {  
  60.             return this.ticksPerSecond;  
  61.         }  
  62.         set  
  63.         {  
  64.             ticksPerSecond = value;  
  65.         }  
  66.     }  
  67.   
  68.     private long baseTime;  
  69.     private long ticksPerSecond;  
  70. }  

調用很簡單:  pwa

    1. AccurateTimerHelper atHelper = new AccurateTimerHelper();  
    2. /* 
    3. //進行不少費時操做 
    4. */  
    5. atHelper.GetElapsedTime()  
相關文章
相關標籤/搜索