TTimer实际上如何在内部运作?

WeG*_*ars 0 windows delphi winapi ttimer rad-studio

间隔设置为1秒的TTimer每1秒发送一条消息.此消息在应用程序的消息循环中处理,这会导致触发OnTimer事件.
如果应用程序繁忙且没有时间处理消息循环,则会跳过OnTimer事件.

我知道TTimer使用内部SetTimer.

我的问题是:

  1. TTimer是否使用内部/单独的线程(通过SetTimer)?
  2. 为什么如果模态MessageDlg"阻塞"表单,那么持有计时器(及其OnTimer偶数)的表单仍可以执行操作?(见下面的代码)
  3. 文件称SetTimer要求Win2000最低限度.如何在Win98中实现TTimer?

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

Ser*_*yuz 6

如果应用程序繁忙且没有时间处理消息循环,则会跳过OnTimer事件.

这是有效的.对MSDN博客文章给一些内部实施细则,尤其是他们提到的到期计时器会导致QS_TIMER消息队列的状态的标志被设置.没有进一步的时间间隔将导致队列状态标志更加设置.设置此标志并且[Peek|Get]Message无法选择任何更高优先级的消息时,将生成计时器消息.

虽然计时器消息不会堆积在队列中,但是可以在执行前一个事件处理程序时再次触发计时器.当处理程序中的代码执行时间超过计时器间隔并允许重入时,这是可能的.如果计时器处理程序导致应用程序处理排队的消息,则可以清除任何挂起的队列状态标志并再次发布消息,这可能导致计时器在处理程序完成执行之前触发.

TTimer是否使用内部/单独的线程(通过SetTimer)?

在主线程中创建一个实用程序窗口,它将接收计时器消息.一旦收到定时器消息,该窗口就会调用事件处理程序(如果已分配一个)

为什么如果模态MessageDlg"阻塞"表单,那么持有计时器(及其OnTimer偶数)的表单仍可以执行操作?

模态循环继续处理队列,它在调用HandleMessage的循环中调用Application ProcessMessage.因此,仍然处理定时器消息.

这是上面提到的重新引入的潜在原因.您可以使用标志或禁用/启用计时器来防止这种情况发生.或者完全分解处理程序中的任何消息处理.

文件称SetTimer要求Win2000最低限度.如何在Win98中实现TTimer

相同.文档不断变化,偶尔MSDN会从最低要求中删除不受支持的操作系统版本 - 相当不一致.我的XE2 API文档说明:

最低操作系统 Windows 95,Windows NT 3.1

对于WM_TIMER消息.