【发布时间】:2022-03-19 04:01:23
【问题描述】:
我正在实现一个计时器,需要它每 50 毫秒左右运行一次,并且希望分辨率为 1 毫秒或更短。我首先阅读了这两篇文章:
http://www.codeproject.com/Articles/1236/Timers-Tutorial
http://www.virtualdub.org/blog/pivot/entry.php?id=272
奇怪的是,它们似乎相互矛盾。有人说队列计时器适用于高分辨率,其他帖子来自 Windows 7 系统,显示分辨率约为 15 毫秒(对于我的应用程序来说不够好)。
所以我在我的系统上进行了测试(Win7 64bit i7-4770 CPU @3.4 Ghz)。我从 50 毫秒开始,这就是我所看到的(从左侧开始的时间,右侧执行之间的间隔;全部以毫秒为单位):
150 50.00
200 50.01
250 50.00
...
450 49.93
500 50.00
550 50.03
...
2250 50.10
2300 50.01
我看到最大误差约为 100 us,平均误差可能约为 30 us。这让我相当高兴。
所以我开始放弃这个时期,看看它在什么时候变得不可靠。一旦我减少了时间
以 5 毫秒为周期,每隔几秒就会看到一些周期在 3 到 6 毫秒之间跳跃的情况并不少见。如果我将周期减少到 1 毫秒,则可以看到 5 到 10 到 40 毫秒的周期。我认为跳跃到 40 毫秒可能是由于我正在将内容打印到屏幕上,我不知道。
这是我的定时器回调代码:
VOID CALLBACK timer_execute(PVOID p_parameter,
BOOLEAN p_timer_or_wait_fired)
{
LARGE_INTEGER l_now_tick;
QueryPerformanceCounter(&l_now_tick);
double now = ((l_now_tick.QuadPart - d_start.QuadPart) * 1000000) / d_frequency.QuadPart;
double us = ((l_now_tick.QuadPart - d_last_tick.QuadPart) * 1000000) / d_frequency.QuadPart;
//printf("\n%.0f\t%.2f", now / 1000.0f, ms / 1000.0f);
if (us > 2000 ||
us < 100)
{
printf("\n%.2f", us / 1000.0f);
}
d_last_tick = l_now_tick;
}
无论如何,只要您以 100hz 或更慢的速度执行,在我看来,队列计时器就是非常好的工具。我链接到的第二篇文章中发布的不良结果(精度为 15 毫秒左右)是否可能是由于 CPU 速度较慢或配置不同?
我想知道我是否可以在多台机器上获得这种性能(所有机器都与运行 64 位 Win7 的机器一样快或更快)?另外,我注意到如果你的回调在这段时间过去之前没有退出,操作系统将在那里放置另一个线程。这可能是显而易见的,但它在任何文档中对我来说并不突出,并且对客户端代码有重大影响。
【问题讨论】:
-
我也在搜索这个,可以说 CreateWaitableTimer-SetWaitableTimer 可以提供更高的精度,它有一个 LARGE_INTEGER 的参数,其间隔为 100ns。你试过了吗? (好吧,您输入已经很久了,但您可能还记得。)
标签: visual-c++ timer windows-7 periodic-task