C#中精確計時的一點收穫

來源:互聯網
上載者:User

以下所有代碼運行環境:Windows 2003, Intel(R) Core(TM) 2 Duo CPU E8400 @  3.00GHz 2.99GHz,2.96GB記憶體

根據綜合網上的一些文章,精確計時主要有以下幾種方式

1 調用WIN API中的GetTickCount
[DllImport("kernel32")]
static extern uint GetTickCount();

從作業系統啟動到現在所經過的毫秒數,精度為1毫秒,經簡單測試發現其實誤差在大約在15ms左右

缺點:傳回值是uint,最大值是2的32次方,因此如果伺服器連續開機大約49天以後,該方法取得的傳回值會歸零

用法:

uint s1 = GetTickCount();Thread.Sleep(2719);Console.WriteLine(GetTickCount() - s1);  //單位毫秒
2 調用WIN API中的timeGetTime  推薦
[DllImport("winmm")]
static extern uint timeGetTime();

常用於多媒體定時器中,與GetTickCount類似,也是返回作業系統啟動到現在所經過的毫秒數,精度為1毫秒。

一般預設的精度不止1毫秒(不同作業系統有所不同),需要調用timeBeginPeriod與timeEndPeriod來設定精度

[DllImport("winmm")]
static extern void timeBeginPeriod(int t);
[DllImport("winmm")]
static extern void timeEndPeriod(int t);

 缺點:與GetTickCount一樣,受傳回值的最大位元限制。

用法:

timeBeginPeriod(1);uint start = timeGetTime();Thread.Sleep(2719);Console.WriteLine(timeGetTime() - start);  //單位毫秒timeEndPeriod(1);
 3 調用.net內建的方法System.Environment.TickCount

擷取系統啟動後經過的毫秒數。經反編譯猜測它可能也是調用的GetTickCount,但是它的傳回值是int,而GetTickCount與timeGetTime方法的原型中傳回值是DWORD,對應C#中的uint,難道.NET對System.Environment.TickCount另外還做了什麼處理嗎?
缺點:與GetTickCount一樣,受傳回值的最大位元限制。

用法:

int aa = System.Environment.TickCount;Thread.Sleep(2719);Console.WriteLine(System.Environment.TickCount - aa); //單位毫秒

 

 :經過測試,發現GetTickCount、System.Environment.TickCount也可以用timeBeginPeriod與timeEndPeriod來設定精度,最高可將精度提高到1毫秒。不知是什麼原因?

 4 調用WIN API中的QueryPerformanceCounter
[DllImport("kernel32.dll ")]
static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);

用於得到高精度計時器(如果存在這樣的計時器)的值。微軟對這個API解釋就是每秒鐘某個計數器增長的數值。
如果安裝的硬體不支援高精度計時器,函數將返回false需要配合另一個API函數QueryPerformanceFrequency。

[DllImport("kernel32")]
static extern bool QueryPerformanceFrequency(ref long PerformanceFrequency);

 QueryPerformanceFrequency返回硬體支援的高精度計數器的頻率,如果安裝的硬體不支援高精度計時器,函數將返回false。

用法:

long a = 0;QueryPerformanceFrequency(ref a);long b = 0, c = 0;QueryPerformanceCounter(ref b);Thread.Sleep(2719);QueryPerformanceCounter(ref c);Console.WriteLine((c - b) / (decimal)a);  //單位秒

精度為百萬分之一秒。而且由於是long型,所以不存在上面幾個API位元不夠的問題。

缺點:在一篇文章看到,該API在節能模式的時候結果偏慢,超頻模式的時候又偏快,而且用電池和接電源的時候效果還不一樣(筆記本)
原文地址:http://delphi.xcjc.net/viewthread.php?tid=1570
未經過超頻等測試,如果是真的,那該API出來的結果就可能不準。

 5 使用.net的System.Diagnostics.Stopwatch類    推薦

Stopwatch 在基礎計時器機制中對計時器的刻度進行計數,從而測量已耗用時間。如果安裝的硬體和作業系統支援高解析度效能的計數器,則 Stopwatch 類將使用該計數器來測量已耗用時間;否則,Stopwatch 類將使用系統計數器來測量已耗用時間。使用 Frequency 和 IsHighResolution 兩個靜態欄位可以確定實現 Stopwatch 計時的精度和解析度。

實際上它裡面就是將QueryPerformanceCounter、QueryPerformanceFrequency兩個WIN API封裝了一下,如果硬體支援高精度,就調用QueryPerformanceCounter,如果不支援就用DateTime.Ticks來計算。

用法:

Stopwatch sw = new Stopwatch();sw.Start();Thread.Sleep(2719);sw.Stop();Console.WriteLine(sw.ElapsedTicks / (decimal)Stopwatch.Frequency);
6 使用CPU時間戳記進行更高精度計時

原文地址:http://www.chinaunix.net/jh/23/110190.html

該方法的原理我不是很明白,硬體知識太匱乏了。精度是ns

在C#中要用該方法必須先建立一個託管C++項目(因為要內嵌彙編),編譯成DLL供c#調用,有點麻煩。

C++代碼:

// MLTimerDot.h#pragma onceusing namespace System;namespace MLTimerDot {        //得到電腦啟動到現在的刻度         unsigned __int64 GetCycleCount(void)         {                 _asm  _emit 0x0F                 _asm  _emit 0x31         }         //聲明 .NET 類         public __gc class MLTimer         {         public:                 MLTimer(void)                 {                                       }                 //計算刻度                UInt64 GetCount(void)                 {                        return GetCycleCount();                 }         }; }

C#調用:

long a = 0;QueryPerformanceFrequency(ref a);MLTimerDot.MLTimer timer = new MLTimerDot.MLTimer();ulong ss= timer.GetCount();Thread.Sleep(2719);Console.WriteLine((timer.GetCount() - ss) / (decimal)a);

缺點:和QueryPerformanceCounter一樣,結果不太穩定。

 

我的結論:常規應用下timeGetTime完全夠用了,將精度調到1毫秒,大部分境況都夠用。System.Diagnostics.Stopwatch由於調用方便,也推薦使用。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.