我的应用程序中有一个TTimer,它每2秒触发一次并调用我的事件处理程序HandleTimerEvent()。 HandleTimerEvent()函数修改共享资源,在返回之前可能需要10秒的时间才能执行。此外,我在事件处理程序中调用Sleep()来有时放弃处理器。
我不确定C ++ builder的TTimer对象在调用事件时是如何工作的,所以我刚才解释的场景让我思考,特别是在先前的调用返回之前是否调用了HandleTimerEvent()。
问题归结为几件事。
TTimer对象是否对事件进行排队?
TTimer对象可以在先前的调用返回之前调用我的事件处理程序吗?
答案 0 :(得分:32)
此回复假定仍然实施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消息。
一个简单的解决方案是在您输入计时器事件处理程序时禁用计时器对象,并在退出计时器事件处理程序时重新启用它。这将阻止在事件处理程序仍在工作时触发计时器消息,无论代码的消息处理特性如何。
答案 1 :(得分:2)
我广泛使用TTimer。它不会对事件进行排队。如果您希望将其移交给事件处理程序,则创建一个处理事件的TThread,以便Timer可以继续它的工作。计时器不是异步操作,而是同步操作。