Как известно, Функция GetTickCount возвращает число миллисекунд, прошедших с момента старта системы, до 49,7 дней 

Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.

GetTickCount function

Как используются тики? 

Обычно с помощью тиков удобно контролировать время выполнения операции, например, выполнение действий по списку, чтобы операция занимала не более 1 секунды: 

DWORD t = GetTickCount(); 

while ( GetTickCount() - t < 1000 ) { 
    // в цикле выполняем шаги длительной операции 
} 

Также тики могут использовать для определения времени запуска компьютера, другими словами, сколько времени работает компьютер после загрузки.   

Особенности GetTickCount 

Тики считаются не по одной миллисекунде, а в соответствии с системным таймером, порядка 10-16 миллисекунд.    

Тики продолжают считаться, даже если компьютер находится в спящем режиме или в режиме гибернации. 

Тики считаются 32-хбитным счётчиком.

Что такое проблема 49,7 дней  

Проблема 49,7 дней возникает из-за переполнения 32-хбитного счетчика миллисекунд, который заполняется до 0xffffffff за 49 дней 17 часов, т.е. примерно 49,7 суток.

На самом деле, когда счётчик переполняется, ничего страшного не происходит – просто счётчик начинается снова считать с нуля, но:

  • Контроль выполнения операции в этом случае сработает некорректно, т.к. условие GetTickCount() — t < 1000 не выполнится. 
  • Точно определить время запуска нельзя, потому что это могло произойти и 49,7 суток тому назад, и 99,4 суток, и даже больше.   

Решения проблемы 49,7 дней 

Перезагрузка компьютера

Исторически самый старый метод, хорош тем, что не требует модификации программ.

Если перезагружать компьютер планово, например, раз в месяц, то он никогда не доработает до 49,7 суток, соответственно, в проблемную ситуацию не попадёт.

Поскольку сервера обычно работают в графике 24х7, то для них желательно запланировать перезагрузку по расписанию, можно настроить и автоматически, см. Выключение или перезагрузка компьютера из bat файла.

Рабочие станции или ноутбуки редко когда работают без перезагрузки так долго, поэтому проблема 49,7 дней для них и раньше не была так актуальна. А сейчас Майкрософт присылает обновления, которые требуют перезагрузки для установки, поэтому приходится перезагружать чаще, чем раз в месяц.

Использовать 64-битную версию GetTickCount 

Функция GetTickCount64 имеет 64-хбитный счётчик. 

https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724411(v=vs.85).aspx 

  • Для 64-хбитного счётчика проблемы 49,7  дней не существует в принципе.
  • Определение времени старта системы с GetTickCount64 будет корректным. 

Функция GetTickCount64 поддерживается только начиная с Windows Vista, а это значит, что программа, использующая GetTickCount64, не заработает в Windows XP. 

Делать сравнение с учётом значения счётчика 

Сравнение с проверкой того, что 32-хбитный счётчик прошёл через ноль, позволяет получить корректное время выполнения текущей операции и сохранить совместимость с Windows XP. 

DWORD t1 = GetTickCount(); 
for ( ;; ) { 
    DWORD t2 = GetTickCount(); 
    DWORD diff = (t2>t1) ? t2-t1 : (0xffffffff-t1)+t2+1; 
    if ( diff > 1000 ) 
        break; 
    // делаем следующий шаг относительно длинной операции  
} 

Опять же, требуется модификация и тестирование используемых программ.

Важно, что при этом всё равно нельзя точно определить время запуска системы! 

Стоит ли использовать текущее время для контроля времени выполнения операции? 

Теоретически, можно использовать текущее время для контроля времени выполнения, то есть вычислять разницу не между отметками тиков, в между отметками времени. 

Но, на практике, присутствует риск корректировки текущего времени между отметками, что может привести к сбою. 

Раньше, когда корректировка системных часов выполнялась только вручную и довольно редко, это риск был небольшим. 

Сейчас, когда все компьютеры имеют настроенную синхронизацию с сервером времени (ntp сервером), корректировка времени может произойти в разные моменты времени, а это значит, что разница между отметками может оказаться некорректной. 

Поэтому лучше использовать именно GetTickCount.

Функция GetTickCount, её особенности и проблема 49,7 дней

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *