• .net平台下获取高精度时间类


    原文:http://www.it118.org/specials/321869dd-98cb-431b-b6d2-82d973cd739d/d940a15c-0d36-4369-8de0-b07cf3f3fd5f.htm

    前言:.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来实现。

    1. using System;  
    2. using System.Runtime.InteropServices;  
    3.   
    4. internal sealed class AccurateTimerHelper  
    5. {  
    6.     public AccurateTimerHelper()  
    7.     {  
    8.         TicksPerSecond = this.GetTicksPerSecond();  
    9.         this.BaseTime = this.GetTime();  
    10.     }  
    11.   
    12.     [DllImport("kernel32.dll", EntryPoint="QueryPerformanceCounter")]  
    13.     private static extern int QueryPerformanceCounter(ref long lpPerformanceCount);  
    14.     [DllImport("kernel32.dll", EntryPoint="QueryPerformanceFrequency")]  
    15.     private static extern int QueryPerformanceFrequency(ref long A_0);  
    16.   
    17.   
    18.     public long GetElapsedTime()  
    19.     {  
    20.         return (long)((((double)(this.GetTime() - this.BaseTime)) / ((double)TicksPerSecond)) * 10000);  
    21.     }  
    22.   
    23.     private long GetTime()  
    24.     {  
    25.         long time = 0;  
    26.         if (AccurateTimerHelper.QueryPerformanceCounter(ref time) == 0)  
    27.         {  
    28.             throw new NotSupportedException("Error while querying the high-resolution performance counter.");  
    29.         }  
    30.         return time;  
    31.     }  
    32.   
    33.     private long GetTicksPerSecond()  
    34.     {  
    35.         long ticksPerSecond = 0;  
    36.         if (AccurateTimerHelper.QueryPerformanceFrequency(ref ticksPerSecond) == 0)  
    37.         {  
    38.             throw new NotSupportedException("Error while querying the performance counter frequency.");  
    39.         }  
    40.         return ticksPerSecond;  
    41.     }  
    42.       
    43.   
    44.     private long BaseTime  
    45.     {  
    46.         get  
    47.         {  
    48.             return baseTime;              
    49.         }  
    50.         set  
    51.         {  
    52.             this.baseTime = value;   
    53.         }  
    54.     }  
    55.   
    56.     private long TicksPerSecond  
    57.     {  
    58.         get  
    59.         {  
    60.             return this.ticksPerSecond;  
    61.         }  
    62.         set  
    63.         {  
    64.             ticksPerSecond = value;  
    65.         }  
    66.     }  
    67.   
    68.     private long baseTime;  
    69.     private long ticksPerSecond;  
    70. }  

    调用很简单:  

      1. AccurateTimerHelper atHelper = new AccurateTimerHelper();  
      2. /* 
      3. //进行很多费时操作 
      4. */  
      5. atHelper.GetElapsedTime()  
  • 相关阅读:
    Ado.Net 实体框架学习笔记3
    Ado.Net 实体框架学习笔记1
    PV3D的小练习~太阳系八大行星
    AS3数组的应用,flash制作流星雨~
    电脑安全措施小贴士(摘)
    Windows下MySql批处理命令
    命令行批量改文件名
    汉字转拼音(asp)(摘录)
    sql server login与user的区别(摘)
    MySql四舍五入
  • 原文地址:https://www.cnblogs.com/anduinlothar/p/3750674.html
Copyright © 2020-2023  润新知