Как TTimer на самом деле работает внутри? - PullRequest
0 голосов
/ 26 сентября 2018

TTimer с интервалом, установленным в 1 секунду, отправляет сообщение каждую 1 секунду.Это сообщение обрабатывается в цикле сообщений приложения, в результате чего вызывается событие OnTimer.
Если приложение занято и не успевает обработать цикл сообщения, событие OnTimer пропускается.

Я знал, что TTimer использует внутренне SetTimer .

Мои вопросы:

  1. Использует ли TTimer внутреннюю / отдельную нить (через SetTimer)?
  2. Почему форма, которая содержит таймер (и даже его OnTimer), все еще может делать вещи, если модальный MessageDlg "блокирует" форму?(см. код ниже)
  3. В документации сказано, что для SetTimer требуется минимум Win2000.Как был реализован TTimer в Win98?

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 Caption = i;
 i++;
 MessageDlg(stuff);      <----- we "block" application here but form's caption is still updated.
}

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Если приложение занято и не успевает обработать цикл сообщений, событие OnTimer пропускается.

Это действительно правильно. Эти и эти сообщения в блоге на MSDN дают некоторые внутренние детали реализации, в частности, они упоминают, что истекающий таймер вызывает установку флага QS_TIMER состояния очереди сообщений.Никакой дальнейший промежуток времени не заставит флаг состояния очереди быть еще более установленным.Когда этот флаг установлен и [Peek|Get]Message не может выбрать любое сообщение с более высоким приоритетом, генерируется сообщение таймера.

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

Использует ли TTimer внутреннюю / отдельную нить (через SetTimer)?

Нет.В главном потоке создается служебное окно, которое будет получать сообщения таймера.После получения сообщения таймера это окно вызывает обработчик события, если он назначен.

Почему форма, которая содержит таймер (и даже его OnTimer), все еще может делать вещи, если модальныйMessageDlg «блокирует» форму?

Модальный цикл продолжает обрабатывать очередь, он вызывает HandleMessage Приложения в цикле, который вызывает ProcessMessage.Следовательно, сообщения таймера все еще обрабатываются.

Это потенциальная причина для повторного входа, упомянутого выше.Вы можете использовать флаг или отключить / включить таймер, чтобы предотвратить это.Или вообще исключить обработку сообщений в обработчике.

В документации сказано, что SetTimer требует минимум Win2000.Как был реализован TTimer в Win98

То же самое.Документация постоянно меняется, иногда MSDN отбрасывает неподдерживаемые версии ОС из минимальных требований - довольно непоследовательно.Моя документация по API XE2 гласит:

Минимум операционных систем Windows 95, Windows NT 3.1

для сообщения WM_TIMER.

0 голосов
/ 26 сентября 2018

Сообщения WM_TIMER никогда не помещаются в очередь сообщений.Они генерируются, когда очередь пуста и установлен флаг, указывающий, что таймер истек.Таким образом, в очереди не может быть более одного сообщения WM_TIMER за раз, и если ваше приложение слишком занято для обработки очереди, вы не получите много сообщений WM_TIMER, ожидающих обработки.

Сообщения WM_PAINT работаюттак же.

...