有时需要对程序的运行时间进行精确的计时,Windows API方法GetTickCount()返回系统启动后的毫秒数,不是很精确.

  Win32 API 使用 QueryPerformanceCounter() 和 QueryPerformanceFrequency() 方法支持高精度计时。这些方法,比“标准的”毫秒精度的计时方法如 GetTickCount() 之类有高得多的精度。另一方面来说,在C# 中使用“非托管”的 API 函数会有一定的开销,但比起使用一点都不精确的 GetTickCount() API 函数来说要好得多了。

  第一个函数 QueryPerformanceCounter() 查询任意时刻高精度计数器的实际值。第二个函数 QueryPerformanceFrequency() 返回高精度计数器每秒的计数值。为了获得某一代码段经历的时间,你需要获得代码段开始前和结束后这两个计时时刻的高精度计数器实际值。这两个值的差指出了代码段执行所经历的时间。然后通过将差除以每秒计数值(高精度计时器频率),就可以计算经过的时间了。
duration = (stop - start) / frequency
经过时间 = (停止时间 - 开始时间) / 频率

C#实现代码

public  class HiPerfTimer   
{   
    [DllImport("Kernel32.dll")]   
    private static extern bool QueryPerformanceCounter(   
        out long lpPerformanceCount);   
    [DllImport("Kernel32.dll")]   
    private static extern bool QueryPerformanceFrequency(   
        out long lpFrequency);   
    private long startTime, stopTime;   
    private long freq;   
    // 构造函数   
    public HiPerfTimer()   
    {   
        startTime = 0;   
        stopTime = 0;   
        if (QueryPerformanceFrequency(out freq) == false)   
        {   
            // 不支持高性能计数器   
            throw new Win32Exception();   
        }   
    }   
    // 开始计时器   
    public void Start()   
    {   
        // 来让等待线程工作   
        Thread.Sleep(0);   
        QueryPerformanceCounter(out startTime);   
    }   
    // 停止计时器   
    public void Stop()   
    {   
        QueryPerformanceCounter(out stopTime);   
    }   
    // 返回计时器经过时间(单位:秒)   
    public double Duration   
    {   
        get  
        {   
            return (double)(stopTime - startTime) / (double)freq;   
        }   
    }   
}

调用方法:

HiPerfTimer pt = new HiPerfTimer();     // 创建新的 HiPerfTimer 对象   
pt.Start();                             // 启动计时器 
 
Console.WriteLine("Test\n");            // 需要计时的代码 
  
pt.Stop();                              // 停止计时器 
  
Console.WriteLine("Duration: {0} sec\n",pt.Duration); // 打印需要计时部分代码的用时

注意:需要添加如下的命名空间

using System; 
using System.Runtime.InteropServices; 
using System.ComponentModel;   
using System.Threading;