2014-01-27 4 views
2

Я столкнулся с странным поведением с ожидаемыми таймерами. Если я создам его с периодом в одну секунду, то после первого стрельбы его последующие стрельбы, похоже, «выровнены» с некоторым миллисекундным значением, которое значительно отличается от первого выстрела.странный вопрос о «выравнивании» таймера по умолчанию

Вот пример огня раз (часы: минуты: 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 

Если я повторно запустить программу, значение миллисекунды первого обжига отличается, но последующие события повторилось при значении 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.

Любой знает, почему это происходит? Я могу себе представить, что может быть какая-то оптимизация системы для сокращения таймерных прерываний и/или контекстных переключателей. Но я нигде не могу найти его документально. Это неожиданно и может привести к проблемам.

ответ

2
dueTime.QuadPart = 0; 

что вы намерены с этим утверждением?

В документации сказано: «Положительные значения указывают на абсолютное время.» И «Отрицательные значения указывают на относительное время.». Zero никогда не указывает возможное значение для 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 
    

Примечание: waitable таймеры позволяют определить надлежащее время в 100 нс единиц. Это не означает, что они могут срабатывать с такой точностью. Точность определяется временной гранулярностью системы. Более подробную информацию о гранулярности системного времени можно найти в ответе this.

+0

Я думал, что значение нуля означает, что первое событие таймера запускается немедленно (как в случае с другими функциями таймера). Кроме того, SetWaitableTimer возвращает TRUE, поэтому я никогда не думал, что ноль является недопустимым значением. MSDN явно не указывать нулевое значение не допускается, и, кроме того, я описал, что он ведет себя корректно. Но изменение времени на другое значение «фиксировало» проблему. Спасибо. – jesse

Смежные вопросы