我的应用程序中有一个每2秒触发一次的TTimer,它调用我的事件处理程序HandleTimerEvent()。HandleTimerEvent()函数修改共享资源,在返回之前可能需要10秒的执行时间。此外,我在事件处理程序中调用了Sleep(),以便有时放弃处理器。
当涉及到调用事件时,我不确定C++构建器的TTimer对象是如何工作的,所以我刚才解释的场景让我开始思考,特别是在返回之前的调用之前是否调用了HandleTimerEvent()。
这个问题可以归结为几件事。
TTimer对象是否对事件进行排队?
在返回之前的调用之前,TTimer对象是否可以调用我的事件处理程序?
发布于 2010-07-23 01:06:35
此回复假设TTimer仍实现为使用WM_Timer消息。如果实现发生了变化(自2005年起),请忽略。
不,TTimer对象不会对事件进行排队。它是由Windows WM_Timer消息驱动的,并且Windows不允许WM_TIMER消息在消息队列中堆叠。如果下一个计时器间隔出现,并且Windows发现应用程序的消息队列中已经有一条WM_Timer消息,它不会向队列中添加另一个WM_Timer消息。( WM_Paint、btw也是如此)
是的,即使前一个事件处理程序仍在执行,也有可能触发TTimer.OnTimer事件。如果您在事件处理程序中执行了任何允许应用程序处理消息的操作,则可以重新进入您的计时器事件。显而易见的是,如果您的事件处理程序调用Application.ProcessMessages,但它可能比这更微妙-如果您在事件处理程序中调用的任何内容内部调用Application.ProcessMessages,或调用PeekMessage/GetMessage + DispatchMessage,或打开模式对话框,或调用绑定到进程外COM对象的COM接口,则将处理应用程序消息队列中的消息,其中可能包括您的下一条WM_Timer消息。
一种简单的解决方案是在进入timer事件处理程序时禁用timer对象,并在退出timer事件处理程序时重新启用它。这将防止在事件处理程序仍在工作时触发计时器消息,而不管代码的消息处理特征如何。
发布于 2010-07-23 01:17:37
我广泛地使用TTimer。它不会对事件进行排队。如果你想把它交给一个事件处理器,那么创建一个处理你的事件的TThread,这样计时器就可以继续它的工作了。定时器不是同步运行的,而是同步运行的。
https://stackoverflow.com/questions/3311246
复制相似问题