高分辨率计数器和定时器应用

代码优化时需要用到精确的计时器。常用的有GetTickCount函数,可以达到毫秒级的精度。但还是很不够的,这时可以采用提高循环次数的办法。另外,还有一个精度更高的定时——“高分辨率性能计数器”(high-resolution performance counter),它提供了两个API函数,取得计数器频率的QueryPerformanceFrequency和取得计数器数值的QueryPerformanceCounter。实现原理是利用计算机中的8253,8254可编程时间间隔定时器芯片实现的。在计算机内部有三个独立的16位计数器。

  计数器可以以二进制或二—十进制(BDC)计数。计数器每秒产生n次脉冲,每次脉冲使计数器的数字减一,产生频率是可变的,用QueryPerformanceFrequency可以得到,比如我的电脑(P4 2.8G)返回的是2793050000,P4 3G则返回2992530000。QueryPerformance Counter可以得到当前的计数器值。所以只要你的计算机够快,理论上精度可以达到1/2793050000秒或者更高。

先看高分辨率计数器的类
public class Counter
{
      protected Int64 m_freq;
      protected bool m_usePerf = true;      //高分辨率计数器是否可用

      public Counter()
      {
            if (QueryPerformanceFrequency(ref m_freq) == 0)
            {
                  m_freq = 1000;
                  m_usePerf = false;
            }
      }     

      // 获取当前的Tick
      public Int64 CurrentTick()
      {
            if (m_usePerf)
            {
                  Int64 curTick = 0;
                  QueryPerformanceCounter(ref curTick);
                  return curTick;
            }
           
            return (Int64)Environment.TickCount;
      }

      // 获取两个时间内的滴答数
      private Int64 GetSafeDelta(Int64 curTime, Int64 prevTime, Int64 maxValue)
      {
            if (curTime < prevTime)
                  return curTime + maxValue - prevTime;

            return curTime - prevTime;
      }
     
      // 获取两个Tick间的时间(毫秒)
      public Int64 DeltaTime_ms(Int64 curTick, Int64 prevTick)
      {
            if (m_usePerf)
                  return 1000 * GetSafeDelta(curTick, prevTick, Int64.MaxValue) / m_freq;

            return GetSafeDelta(curTick, prevTick, Int32.MaxValue);
      }

     

      [System.Runtime.InteropServices.DllImport("KERNEL32.dll")]
      internal static extern int QueryPerformanceFrequency(ref Int64 lpFrequency);

      [System.Runtime.InteropServices.DllImport("KERNEL32.dll")]
      internal static extern int QueryPerformanceCounter(ref Int64 lpPerformanceCount);
}


应用:
Counter counter = new Counter();

flag = true;
while(flag)
{
      Int64 startTick = counter.CurrentTick();
      TickCount++;

      if(TickCount % FramesPerSecond == 0)
            label9.Text = (TickCount / FramesPerSecond).ToString();

      // 按帧更新屏幕
      label3.Text = TickCount.ToString();

      Int64 deltaMs = counter.DeltaTime_ms(counter.CurrentTick(), startTick);
      Int64 targetMs = (Int64)(1000.0F * SecondsPerFrame);      // 如果FramesPerSecond不能被1整除,那么这里会有走时误差

    dt = dt.AddMilliseconds(targetMs);
      label1.Text = dt.ToString() + " " + dt.Millisecond;
     
      if (deltaMs <= targetMs)
      {
            label4.Text = counter.CurrentTick().ToString();

            // 在时间帧到达之前空循环
            while (counter.DeltaTime_ms(counter.CurrentTick(), startTick) < targetMs)
            {
                  Thread.Sleep(0);
                  Application.DoEvents();
            }
      }
}


完整代码下载

转载于:https://www.cnblogs.com/Truly/archive/2006/04/17/377606.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值