在 C#开发过程中,经常需要用到定时器,如果只是为了开启一个线程,或者异步的做一些事情倒还好,直接使用 Form 或者 Thread 的 Timer 功能即可。
但是如果需求是比较精确的计时功能,这个 Timer 就极不好用了,因为他们是线程上的定时器,会受到系统调度的干扰,精度非常差,CPU 使用率高一点点就会影响计时精度。
常用的 Windows API 方法 GetTickCount() 返回系统启动后经过的毫秒数。另一方面,GetTickCount() 函数仅有 1ms 的分辨精度,精度也很不好。
我们要另外寻找一种方法来精确测量时间。
Win32 API 使用 QueryPerformanceCounter() 和 QueryPerformanceFrequency() 方法支持高精度计时。这些方法,比“标准的”毫秒精度的计时方法如 GetTickCount() 之类有高得多的精度。
虽然在 C# 中使用“非托管”的 API 函数会有一定的开销,但比起使用一点都不精确的 GetTickCount() API 函数来说要好得多了。
下面的类实现了 QueryPerformanceCounter() 和 QueryPerformanceFrequency() API 函数功能的封装。
using System;using System.Runtime.InteropServices;using System.ComponentModel;using System.Threading;namespace Win32{internal class HighTimer{[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 HighTimer(){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;}}}}
上面封装类的使用方法:
HighTimer pt = new HighTimer(); // 创建新的 HighTimer 对象pt.Start(); // 启动计时器Console.WriteLine("Test/n"); // 需要计时的代码pt.Stop(); // 停止计时器Console.WriteLine("Duration: {0} sec/n", pt.Duration); // 打印需要计时部分代码的用时
2937
下载ECAD模型