.net平台下获取高精度时间类
前言:.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的计时器是您非常好的选择。
.NET 2.0前运行库中不存在高精度的计时器,而您又需要它,解决的方法是通过调用QueryPerformanceFrequency 和 QueryPerformanceCounter这两个Win32 API来实现。
- using System;
- using System.Runtime.InteropServices;
- internal sealed class AccurateTimerHelper
- {
- public AccurateTimerHelper()
- {
- TicksPerSecond = this.GetTicksPerSecond();
- this.BaseTime = this.GetTime();
- }
- [DllImport("kernel32.dll", EntryPoint="QueryPerformanceCounter")]
- private static extern int QueryPerformanceCounter(ref long lpPerformanceCount);
- [DllImport("kernel32.dll", EntryPoint="QueryPerformanceFrequency")]
- private static extern int QueryPerformanceFrequency(ref long A_0);
- public long GetElapsedTime()
- {
- return (long)((((double)(this.GetTime() - this.BaseTime)) / ((double)TicksPerSecond)) * 10000);
- }
- private long GetTime()
- {
- long time = 0;
- if (AccurateTimerHelper.QueryPerformanceCounter(ref time) == 0)
- {
- throw new NotSupportedException("Error while querying the high-resolution performance counter.");
- }
- return time;
- }
- private long GetTicksPerSecond()
- {
- long ticksPerSecond = 0;
- if (AccurateTimerHelper.QueryPerformanceFrequency(ref ticksPerSecond) == 0)
- {
- throw new NotSupportedException("Error while querying the performance counter frequency.");
- }
- return ticksPerSecond;
- }
- private long BaseTime
- {
- get
- {
- return baseTime;
- }
- set
- {
- this.baseTime = value;
- }
- }
- private long TicksPerSecond
- {
- get
- {
- return this.ticksPerSecond;
- }
- set
- {
- ticksPerSecond = value;
- }
- }
- private long baseTime;
- private long ticksPerSecond;
- }
调用很简单:
- AccurateTimerHelper atHelper = new AccurateTimerHelper();
- /*
- //进行很多费时操作
- */
- atHelper.GetElapsedTime()