间隔设置为1秒的TTimer每1秒发送一条消息。此消息将在应用程序的消息循环中处理,这将导致触发OnTimer事件。
如果应用程序很忙,并且没有时间处理消息循环,则跳过OnTimer事件。
我知道TTimer在内部使用SetTimer。
我的问题是:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Caption = i;
i++;
MessageDlg(stuff); <----- we "block" application here but form's caption is still updated.
}
发布于 2018-09-26 07:18:14
如果应用程序很忙,并且没有时间处理消息循环,则跳过OnTimer事件。
这实际上是正确的。MSDN上的这和这博客文章给出了一些内部实现细节,特别是它们提到,过期的计时器会导致设置消息队列状态的QS_TIMER
标志。没有更长的时间间隔会导致队列状态标志被设置得更多。当设置此标志且[Peek|Get]Message
无法选择任何更高优先级的消息时,将生成一个定时器消息。
虽然定时器消息不会堆积在队列中,但在执行前一个事件处理程序时,可以再次触发timer。当处理程序中的代码执行时间超过计时器间隔,并且允许重入时,这是可能的。如果计时器处理程序导致应用程序处理排队的消息,则可能清除任何挂起的队列状态标志,并再次发布消息,这可能会导致定时器在处理程序完成执行之前触发。
TTimer是否使用内部/单独的线程(通过SetTimer)?
不是的。在主线程中创建一个实用程序窗口,它将接收计时器消息。收到定时器消息后,如果指定了一个事件处理程序,此窗口将调用事件处理程序。
如果模态OnTimer正在“阻塞”表单,为什么持有定时器的表单(甚至它的MessageDlg )仍然可以执行任务?
模态循环继续处理队列,它在调用ProcessMessage
的循环中调用应用程序的ProcessMessage
。因此,计时器消息仍然被处理。
这是上述重新进入的一个潜在原因。您可以使用标志或禁用/启用计时器来防止这种情况发生。或将处理程序中的任何消息处理完全排除在外。
文档显示,SetTimer需要Win2000最小值。TTimer是如何在Win98中实现的
一样的。文档不断变化,偶尔MSDN会从最低要求中删除不支持的OS版本--这是不一致的。我的XE2 API文档声明:
最低操作系统 Windows 95,WindowsNT3.1
对于WM_TIMER
消息。
发布于 2018-09-26 03:53:38
WM_TIMER消息从未放置在消息队列中。当队列为空并设置了指示计时器过期的标志时,将生成它们。因此,队列中一次不可能有多个WM_TIMER消息,如果应用程序太忙,无法处理队列,则不会收到大量等待处理的WM_TIMER消息。
WM_PAINT消息的工作方式是相同的。
https://stackoverflow.com/questions/52516692
复制相似问题