Подтвердить что ты не робот

Является ли обработчик событий TTimer.OnTimer реентерабельным?

У меня есть TTimer в моем приложении, который срабатывает каждые 2 секунды и вызывает мой обработчик событий HandleTimerEvent(). Функция HandleTimerEvent() изменяет общие ресурсы и может потребоваться 10 секунд для выполнения перед возвратом. Кроме того, я вызываю Sleep() в обработчике событий, чтобы время от времени отказываться от процессора.

Я не уверен, как работает объект TTimer для С++, когда дело доходит до вызывающих событий, поэтому сценарий, который я только что объяснил, заставил меня задуматься, в частности, вызывает ли HandleTimerEvent() до того, как предыдущий вызов вернулся.

Вопрос сводится к нескольким вещам.

Объект TTimer останавливает события?

Может ли объект TTimer вызывать мой обработчик событий до возврата предыдущего вызова?

4b9b3361

Ответ 1

Этот ответ предполагает, что TTimer все еще используется для использования сообщений WM_Timer. Если реализация изменилась (с 2005 года), пожалуйста, не обращайте внимания.

Нет, объект TTimer не помещает в очередь события. Это обусловлено сообщением Windows WM_Timer, и Windows не позволяет сообщениям WM_TIMER складываться в очереди сообщений. Если следующий интервал таймера происходит, и Windows видит, что сообщение WM_Timer уже находится в очереди сообщений приложения, оно не добавляет в очередь еще одну mess_age WM_Timer. (То же самое для WM_Paint, кстати)

Да, возможно, что событие TTimer.OnTimer будет запущено, даже если предыдущий обработчик событий все еще выполняется. Если вы делаете что-либо в своем обработчике событий, что позволяет приложению обрабатывать сообщения, ваше событие таймера может быть повторно введено. Очевидным является то, что обработчик событий вызывает Application.ProcessMessages, но он может быть намного более тонким, чем это - если что-либо, что вы вызываете в обработчике событий, внутренне вызывает Application.ProcessMessages или вызывает PeekMessage/GetMessage + DispatchMessage или открывает модальный диалог, или вызывает COM-интерфейс, привязанный к COM-объекту вне процесса, тогда сообщения в очереди сообщений вашего приложения будут обработаны и могут включать в себя следующее сообщение WM_Timer.

Простое решение - отключить объект таймера при вводе обработчика события таймера и повторно использовать его при выходе из обработчика события таймера. Это предотвратит запуск сообщений таймера, пока ваш обработчик событий все еще работает, независимо от характеристик обработки сообщений вашего кода.

Ответ 2

Я использую TTimer широко. Он не ставит в очередь события. Если вы хотите, чтобы он передал обработчик события, создайте TThread, который обрабатывает ваши события, чтобы таймер мог продолжить работу. Таймер не работает асинхронно, а скорее синхронно.