我的应用程序中有一个 TTimer,每 2 秒触发一次并调用我的事件处理程序 HandleTimerEvent()。 HandleTimerEvent() 函数会修改共享资源,并且在返回之前可能需要 10 秒的时间来执行。此外,我有时会在事件处理程序中调用 Sleep() 来放弃处理器。
我不确定 C++ builder 的 TTimer 对象在调用事件时如何工作,因此我刚刚解释的场景让我思考,特别是在先前的调用返回之前是否调用 HandleTimerEvent() 。
这个问题归结为几件事。
TTimer 对象是否对事件进行排队?
TTimer 对象可以在先前的调用返回之前调用我的事件处理程序吗?
此回复假设 TTimer 仍被实现为使用 WM_Timer 消息。如果实施方式发生变化(自 2005 年以来),请忽略。
不,TTimer 对象不会对事件进行排队。它是由Windows WM_TIMER消息驱动的,Windows不会让WM_TIMER消息在消息队列中堆积。如果出现下一个计时器间隔并且 Windows 发现应用程序的消息队列中已存在 WM_Timer 消息,则它不会向队列中添加另一个 WM_Timer 消息。 (顺便说一句,与 WM_Paint 相同)
是的,即使先前的事件处理程序仍在执行,TTimer.OnTimer 事件也可能被触发。如果您在事件处理程序中执行任何允许应用程序处理消息的操作,则可以重新输入计时器事件。显而易见的是,如果您的事件处理程序调用 Application.ProcessMessages,但它可能比这更微妙 - 如果您在事件处理程序中调用的任何内容在内部调用 Application.ProcessMessages,或调用 PeekMessage/GetMessage + DispatchMessage,或打开模式对话框,或调用绑定到进程外 COM 对象的 COM 接口,然后应用程序消息队列中的消息将被处理,并且可能包括下一条 WM_Timer 消息。
一个简单的解决方案是在进入计时器事件处理程序时禁用计时器对象,并在退出计时器事件处理程序时重新启用它。这将防止在事件处理程序仍在工作时触发计时器消息,无论代码的消息处理特性如何。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)