2

I faced a strange behavior with waitable timers. If I create it with one-second period then after the first firing, its following firings seem to be "aligned" to some millisecond value which differs significantly from first firing.

Here is example of fire times (hours:minutes:seconds.milliseconds):

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

If I re-run the program, the millisecond value of first firing is different, but the subsequent events happen again at 238 value.

Here is test code I used:

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;
}

I see this issue in Windows 7 and Windows Server 2008 R2, but not in Windows XP/Server 2003.

Anyone knows why this happens? I can imagine it can be some system optimization to reduce timer interrupts and/or context switches. But I can't find it documented anywhere. It is unexpected and can lead to issues.

jesse
  • 650
  • 5
  • 19

1 Answers1

2
dueTime.QuadPart = 0;

what do you intend with this statement?

The documentation says: "Positive values indicate absolute time." and "Negative values indicate relative time.". Zero never specifies a possible value for dueTime.

Instead you shoud find a reasonable start time by specifying

  1. a relative time for the first event to happen.

    dueTime.QuadPart = -1000000; 
    // 100 ns units, first event at 100 ms from now
    
  2. an absolute time

    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
    

Note: waitable timers allow to specify the due time in 100 ns units. This does not mean that they can trigger at that accuracy. The accuracy is determined by the system time granularity. More details about the system time granularity can be found in this answer.

Community
  • 1
  • 1
Arno
  • 4,994
  • 3
  • 39
  • 63
  • I thought zero value means first timer event is fired immediately (as in case with other timer functions). Besides SetWaitableTimer returns TRUE, so I never thought zero is invalid value. MSDN do not explicitly specify zero is not allowed, and besides of issue I described it behaves correctly. But changing due time to other value "fixed" the problem. Thank you. – jesse Jan 27 '14 at 17:25