奇怪的等待计时器“对齐”问题

时间:2014-01-27 15:26:30

标签: windows winapi visual-c++ timer

我遇到了一个与等待计时器的奇怪行为。如果我用一秒钟的时间创建它,那么在第一次射击之后,它的后续射击似乎“对齐”到某个毫秒值,这与第一次射击明显不同。

以下是开火时间的示例(小时:分钟:秒。毫秒):

18:06:25.753  <-- here 753
18:06:26.238  <-- here and later 238
18:06:27.238
18:06:28.238
18:06:29.238

如果我重新运行程序,第一次触发的毫秒值不同,但后续事件再次发生在238值。

以下是我使用的测试代码:

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
    LARGE_INTEGER dueTime;
    dueTime.QuadPart = 0;
    SetWaitableTimer(hTimer, &dueTime, 1000, NULL, NULL, FALSE);

    for (int i=0; i<10; i++)
    {
        WaitForSingleObject(hTimer, INFINITE);

        SYSTEMTIME st;
        GetLocalTime(&st);
        printf("%02d:%02d:%02d.%03d\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    }

    return 0;
}

我在Windows 7和Windows Server 2008 R2中看到此问题,但在Windows XP / Server 2003中没有。

任何人都知道为什么会这样?我可以想象,可以通过一些系统优化来减少定时器中断和/或上下文切换。但我无法在任何地方找到它。这是意料之外的,可能导致问题。

1 个答案:

答案 0 :(得分:2)

dueTime.QuadPart = 0;
你对这个陈述有什么打算?

文档说:“正值表示绝对时间。”和“负值表示相对时间。”。零从不指定dueTime的可能值。

相反,您应通过指定

来找到合理的开始时间
  1. 第一个事件发生的相对时间。

    dueTime.QuadPart = -1000000; 
    // 100 ns units, first event at 100 ms from now
    
  2. 绝对时间

    FILETIME FileTime;
    LARGE_INTEGER dueTime;
    
    GetSystemTimeAsFileTime(&FileTime);
    CopyMemory(&dueTime,&FileTime,sizeof(FILETIME));
    dueTime.QuadPart += 1000000; 
    // 100 ns units, first event at 100 ms from FileTime
    
  3. 注意:等待定时器允许以100 ns为单位指定到期时间。这并不意味着它们可以以这种准确度触发。准确性由系统时间粒度决定。有关系统时间粒度的更多详细信息,请参阅this answer。