.net中除了使用Stopwatch计时,还可以使用一些windows API实现计时功能。下面是相关的windows API:
1 /// <summary> 检索自系统启动以来经过的毫秒数,最多49.7天。 </summary> 2 /// <returns>返回值是自系统启动以来经过的毫秒数。DWORD </returns> 3 /// <remarks>GetTickCount功能限于系统定时器,这是通常在10毫秒到16毫秒的范围内的分辨率。 4 /// GetTickCount函数的分辨率不受GetSystemTimeAdjustment函数所做的调整的影响 。</remarks> 5 [DllImport("kernel32")] 6 public static extern uint GetTickCount(); 7 8 /// <summary> 检索自系统启动以来经过的毫秒数。 </summary> 9 /// <returns>毫秒数。ULONGLONG </returns> 10 /// <remarks>GetTickCount64功能限于系统定时器,这是通常在10毫秒到16毫秒的范围内的分辨率。 11 /// GetTickCount64函数的分辨率不受GetSystemTimeAdjustment函数所做的调整的影响 。</remarks> 12 [DllImport("kernel32")] 13 public static extern ulong GetTickCount64(); 14 15 /// <summary> 检索系统时间,以毫秒为单位。系统时间是自Windows启动以来经过的时间。 </summary> 16 /// <returns>返回系统时间(以毫秒为单位)。DWORD</returns> 17 /// <remarks>请注意,timeGetTime函数返回的值是DWORD值。该返回值每2 ^ 32毫秒回绕到0,大约49.71天。这会在直接在计算中使用timeGetTime返回值的代码中引起问题, 18 /// 尤其是在该值用于控制代码执行的情况下。您应该始终在计算中使用两个timeGetTime返回值之间的差。 19 /// timeGetTime函数的默认精度可以是5毫秒或更多,具体取决于机器。您可以使用timeBeginPeriod和timeEndPeriod函数来提高timeGetTime的精度。 20 /// 如果这样做,timeGetTime返回的连续值之间的最小差异可能与使用timeBeginPeriod和timeEndPeriod设置的最小周期值一样大。</remarks> 21 [DllImport("winmm", EntryPoint = "timeGetTime")] 22 public static extern uint TimeGetTime(); 23 24 /// <summary> 要求定期定时器的最小分辨率。 </summary> 25 /// <param name="uPeriod">应用程序或设备驱动程序的最小计时器分辨率(以毫秒为单位)。较低的值表示较高的(更准确的)分辨率。UINT </param> 26 /// <returns>返回TIMERR_NOERROR(0)如果成功或TIMERR_NOCANDO(97)如果在指定的分辨率uPeriod是超出范围。MMRESULT(uint)</returns> 27 [DllImport("winmm", EntryPoint = "timeBeginPeriod")] 28 public static extern uint TimeBeginPeriod(int uPeriod); 29 30 /// <summary> 清除先前设定的最小计时器分辨率。 </summary> 31 /// <param name="uPeriod">在上一次调用timeBeginPeriod函数中指定的最小计时器分辨率。UINT </param> 32 /// <returns>返回TIMERR_NOERROR(0)如果成功或TIMERR_NOCANDO(97)如果在指定的分辨率uPeriod是超出范围。MMRESULT(uint)</returns> 33 [DllImport("winmm", EntryPoint = "timeEndPeriod")] 34 public static extern uint TimeEndPeriod(int uPeriod); 35 36 /// <summary> 检索性能计数器的当前值,这是一个高分辨率(小于1us)时间戳,可用于时间间隔测量。 </summary> 37 /// <param name="lpPerformanceCount">指向接收当前性能计数器值(以计数为单位)的变量的指针。LARGE_INTEGER </param> 38 /// <returns>如果函数成功,则返回值为非零。如果函数失败,则返回值为零。要获取扩展的错误信息,请调用GetLastError。 39 /// 在运行Windows XP或更高版本的系统上,该函数将始终成功执行,因此永远不会返回零。</returns> 40 [DllImport("kernel32")] 41 public static extern short QueryPerformanceCounter(ref long lpPerformanceCount); 42 43 /// <summary> 检索性能计数器的频率。性能计数器的频率在系统启动时是固定的,并且在所有处理器之间均保持一致。 44 /// 因此,只需要在应用程序初始化时查询频率,就可以缓存结果。</summary> 45 /// <param name="lpFrequency">指向接收当前性能计数器频率的变量的指针,以每秒计数为单位。LARGE_INTEGER </param> 46 /// <returns>如果安装的硬件支持高分辨率性能计数器,则返回值为非零。如果函数失败,则返回值为零。要获取扩展的错误信息,请调用GetLastError。 47 /// 在运行Windows XP或更高版本的系统上,该函数将始终成功执行,因此永远不会返回零。</returns> 48 [DllImport("kernel32")] 49 public static extern short QueryPerformanceFrequency(ref long lpFrequency);
获取或计算系统开机时间的方法:
1 //测试处理器 i7-4700MQ 2 using (PerformanceCounter pc = new PerformanceCounter("System", "System Up Time")) { 3 pc.NextValue(); //The first call returns 0, so call this twice 4 float nextValue = pc.NextValue(); 5 DateTime time = DateTime.Now; 6 Console.WriteLine(time.AddTicks(-TimeSpan.FromSeconds(nextValue).Ticks).ToString("O") + " System Up Time"); 7 } 8 9 SelectQuery query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary=‘true‘"); 10 ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); 11 foreach (ManagementBaseObject o in searcher.Get()) { 12 ManagementObject mo = (ManagementObject)o; 13 string date = mo.Properties["LastBootUpTime"].Value.ToString(); 14 DateTime dtBootTime = ManagementDateTimeConverter.ToDateTime(date); 15 Console.WriteLine(dtBootTime.ToString("O") + " SELECT LastBootUpTime FROM Win32_OperatingSystem "); 16 } 17 18 //上面两个比QueryPerformanceCounter计算出来的快150ms左右 19 20 long x = 0; 21 QueryPerformanceCounter(ref x); 22 Console.WriteLine(DateTime.Now.AddTicks(-x).ToString("O") + " QueryPerformanceCounter "); 23 24 //下面比QueryPerformanceCounter计算出来的慢160ms左右 25 26 Console.WriteLine(DateTime.Now.AddMilliseconds(-Environment.TickCount).ToString("O") + " Environment.TickCount "); 27 Console.WriteLine(DateTime.Now.AddMilliseconds(-GetTickCount()).ToString("O") + " GetTickCount "); 28 Console.WriteLine(DateTime.Now.AddMilliseconds(-(long)GetTickCount64()).ToString("O") + " GetTickCount64 "); 29 TimeBeginPeriod(1); 30 Console.WriteLine(DateTime.Now.AddMilliseconds(-TimeGetTime()).ToString("O") + " TimeGetTime "); 31 TimeEndPeriod(1); 32 long z = 0; 33 QueryPerformanceCounter(ref x); 34 DateTime now = DateTime.Now; 35 QueryPerformanceCounter(ref z); 36 //DateTime.Now消耗大概1 - 3微秒 37 Console.WriteLine("DateTime.Now消耗(单位100ns):" + (z - x)); 38 Console.ReadKey();