無論你是搞技術研究還是搞項目開發,高精度的時間測量在很多場合下都是必需的。xiaotie 在其《dotnet下時間精度測量》提到了一個 QueryPerfCounter,它對目前還在使用 Microsoft .NET Framework v1.1 的開發人員來說的確是一個好幫手。但若你已經用上了 Microsoft .NET Framework v2.0,那麼 Stopwatch 將會成爲你進行高精度時間測量的不二選擇。
1. 測試 Stopwatch
這裏,我借用一下 xiaotie 在《dotnet下時間精度測量》的測試代碼,並給出對應的運行結果:
static void Test1()
{
Stopwatch sw = new Stopwatch();
sw.Start();
sw.Stop();
Console.WriteLine("Stopwatch 時間精度:{0}ms", sw.ElapsedMilliseconds);
}
// Output:
//
// Stopwatch 時間精度:0ms
static void Test2()
{
Stopwatch sw = new Stopwatch();
int loop = 10000;
int exCount = 0;
for (int i = 0; i < loop; i++)
{
sw.Reset();
sw.Start();
sw.Stop();
if (sw.ElapsedMilliseconds != 0)
{
exCount++;
Console.WriteLine("Stopwatch 時間精讀異常:{0}ms", sw.ElapsedMilliseconds);
}
}
Console.WriteLine("共進行{0}次 Stopwatch 的時間精度測試", loop);
Console.WriteLine("其中{0}次 Stopwatch 的時間精度異常", exCount);
Console.WriteLine("時間校準有效性{0}%", 100 - (100.0 * exCount) / loop);
}
// Output:
//
// 共進行10000次 Stopwatch 的時間精度測試
// 其中0次 Stopwatch 的時間精度異常
// 時間校準有效性100%
static void Test3()
{
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 200; i++)
{
sw.Reset();
sw.Start();
sw.Stop();
Console.WriteLine("Stopwatch 時間精度:{0}ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
int j = 0;
for (j = 0; j < i; j++)
{
int l;
}
sw.Stop();
Console.WriteLine("第{0}次循環,耗時{1}ms", i, sw.ElapsedMilliseconds);
Console.WriteLine();
}
}
// Partial output:
//
// Stopwatch 時間精度:0ms
// 第10次循環,耗時0ms
//
// Stopwatch 時間精度:0ms
// 第12次循環,耗時0ms
//
// Stopwatch 時間精度:0ms
// 第16次循環,耗時0ms
從測試結果中可以看到,Stopwatch 絕對能夠滿足挑剔的你!怎麼樣?手癢了嗎?
2. 應用 Stopwatch
Stopwatch 位於 System.Diagnostics 命名空間中,它的使用方法非常簡單,只要你會用一般的計時器,你就會使用它。
2.1 創建實例
你可以通過 new 或者 Stopwatch.StartNew() 來創建一個 Stopwatch 實例:
Stopwatch sw1 = new Stopwatch();
Stopwatch sw2 = Stopwatch.StartNew();
使用 StartNew() 會創建一個 Stopwatch 實例並馬上開始計時,即等效於如下代碼:
Stopwatch sw2 = new Stopwatch();
sw2.Start();
2.2 測量時間
sw1.Start();
// Do something here
sw2.Stop();
long elaspsedMilliseconds = sw1.ElaspedMilliseconds;
2.3 應用示例
微軟官方提供了一系列示範程序用於演示 Visual Studio 2005,其中 Basic Class Library 部分帶有一個 Stopwatch 的 Windows Forms 示例程序,你可以到 101 Samples for Visual Studio 2005 下載示例代碼。
3. 深入 Stopwatch
Stopwatch 內部也調用了 QueryPerformanceCounter() 和 QueryPerformanceFrequency() 兩個函數,與 QueryPerfCounter 不同的是,當 Stopwatch 檢測到當前的系統和硬件不支持高精度的計數器時,它將轉用我們所熟悉的 DateTime 做法。
Stopwatch 在其靜態構造器中調用 QueryPerformanceFrequency(),透過該函數的返回值判斷當前的系統和硬件是否支持高精度的計數器,並設置 IsHighResolution 屬性的值。Stopwatch 內部用於計算時間間隔的主要方法都會根據 IsHighResolution 的值來選擇合適的計算方法。有興趣的話,你可以使用 Reflector 探究一下 Stopwatch 的內部