C++ 如何在WinXP下获得准确的1ms计时器刻度

C++ 如何在WinXP下获得准确的1ms计时器刻度,c++,windows,winapi,timer,real-time,C++,Windows,Winapi,Timer,Real Time,我尝试每隔1毫秒调用一个函数。问题是,我喜欢在windows上这样做。所以我尝试了多媒体定时器API 多媒体定时器API 来源 idTimer = timeSetEvent( 1, 0, TimerProc, 0, TIME_PERIODIC|TIME_CALLBACK_FUNCTION ); 我的结果是,大多数时间1毫秒是可以的,但有时我会得到双周期。看到1.95毫秒左右的小肿块了吗 我的第一个想法是,也许我的方法运行得太长了。但

我尝试每隔1毫秒调用一个函数。问题是,我喜欢在windows上这样做。所以我尝试了多媒体定时器API

多媒体定时器API 来源

idTimer = timeSetEvent( 
     1, 
     0,
     TimerProc, 
     0, 
     TIME_PERIODIC|TIME_CALLBACK_FUNCTION ); 
我的结果是,大多数时间1毫秒是可以的,但有时我会得到双周期。看到1.95毫秒左右的小肿块了吗

我的第一个想法是,也许我的方法运行得太长了。但我已经测量过了,事实并非如此

排队计时器API 我的下一次尝试是将queud timers API与

hTimerQueue = CreateTimerQueue();
if(hTimerQueue == NULL)
{
printf("Error creating queue: 0x%x\n", GetLastError());
}

BOOL res = CreateTimerQueueTimer(
&hTimer, 
hTimerQueue, 
TimerProc, 
NULL, 
0, 
1,  // 1ms
    WT_EXECUTEDEFAULT);
但结果也不尽如人意。现在我大部分时间都是2毫秒循环时间。

测量 为了测量时间,我使用了QueryPerformanceCounter和QueryPerformanceFrequency方法

问题: 所以现在我的问题是,是否有人在windows下遇到了类似的问题,甚至可能找到了解决方案


谢谢。

如果不使用实时操作系统,就不能指望每隔一毫秒调用一次功能


在不是实时操作系统的Windows上(对于Linux,类似于此),一个以微秒精度重复读取当前时间并在直方图中存储连续差异的程序的非空存储空间大于10毫秒!这意味着您有时会有2毫秒的通话时间,但您也可以在通话之间获得更多的通话时间。

您可以在退出前尝试在程序开始和
timeEndPeriod(1)
运行。这可能会提高计时器精度。

调用
ntquerytimeresolution()
将返回实际解析的值。在您的例子中,实际分辨率几乎肯定是0.9765625 ms。这正是您在第一个图中显示的。 大约1.95毫秒的第二次出现更准确地说是睡眠(1)=1.9531毫秒=2 x 0.9765625毫秒

我猜中断时间大约为1ms(0.9765625)

现在问题开始了:当期望的延迟到期时,计时器发出信号

假设实际分辨率设置为0.9765625,系统的中断心跳将以0.9765625毫秒周期或1024赫兹运行,并以1毫秒的期望延迟调用
睡眠
。将研究两种情况:

  • 在下一次中断前<1ms(ΔT)进行调用。下一次中断将不会确认所需的时间段是否已过期。只有以下中断才会导致调用返回。由此产生的睡眠延迟为ΔT+0.9765625 ms
  • 在下一次中断之前,调用时间>=1ms(ΔT)。下一个中断将强制调用返回。由此产生的睡眠延迟为ΔT
  • 因此,结果在很大程度上取决于呼叫的时间,因此您可能会观察到0.98毫秒事件以及1.95毫秒事件

    编辑:使用
    CreateTimerQueueTimer
    将观察到的延迟推至1.95,因为计时器滴答声(中断周期)为0.9765625毫秒。在第一次发生中断时,请求的1毫秒持续时间尚未完全过期,因此只有在第二次中断后才会触发
    TimerRoc
    (2 x 0.9765625 ms=1.953125 ms>1 ms)。因此,queueTimer图显示峰值为1.953125 ms

    注意:此行为在很大程度上取决于底层硬件


    更多细节可以在

    +1上找到,因为每个人都喜欢简洁的图形:)你对Windows的期望很高。@Bob Moore补充了一个答案,其中包含了这一点。答案已被删除,但我发现这个链接对于操作系统中的计时问题是一个有趣的阅读(真正的操作系统是旧的windows,但概念很可能仍然适用于当前版本)timeSetEvent()创建了一个非常好的计时器。但是它不能抢占高优先级内核线程。schoetbi:在XP上,您将拥有一次禁用数百毫秒中断的驱动程序。见鬼,几个主板将暂停操作系统数毫秒。在通用操作系统上,试图获得这种分辨率级别的isoch是非常困难的。Vista和Win7使获得isoch变得更容易,但它们仍然不是完美的。对于>10毫秒的非空垃圾箱,你到底是什么意思?你的意思是获得时间需要10毫秒以上吗?这是正确的。除了调用两次函数以获取时间外,不做任何操作都会导致时间差超过10毫秒。非常罕见,根据实际计算机,每分钟或每小时一次,但这种情况会发生!非实时操作系统不提供时间保证,但这并不意味着你最终会得到长时间的延迟。通常可以严格控制工作,这样你就有很高的概率,即几乎确定的概率,及时完成工作。虽然我认为这里的问题更多地与计时器粒度和性能有关,而不是与实时性有关,但在我的机器上不是这样。无论如何,谢谢:-)