我花了一些时间试图研究一个明确的答案,但找不到可靠的来源。
我的方案相当简单。 我有一个带有消息泵设置的线程,该线程正在处理来自计时器的重复事件。 以下是消息泵源:
// create timer that goes off every 500 ms
UINT_PTR myTimerID = SetTimer(NULL, 0, 500, TimerCallback);
// message structure
MSG msg;
// process and handle messages for this thread
BOOL getMessageStatus;
while((getMessageStatus = GetMessage(&msg, NULL, 0, 0)) != 0)
{
// failed get message
if(getMessageStatus == -1)
{
printf("GetMessage FAILED!n");
}
// process timer message
else if(msg.message == WM_TIMER)
{
// invoke callback
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
如果计时器回调的时间超过 500 毫秒,计时器将再次触发其事件。 由于回调是在与消息泵相同的线程上执行的,因此我假设回调必须在消息泵处理下一个计时器消息之前完成。
这是对的吗?
SetTimer()
是基于消息的计时器。 计时器经过后,它会在消息队列中设置一个特殊标志。 当您为新消息泵送队列时,如果已设置该标志并且队列中未等待其他更高优先级的消息,则将创建WM_TIMER
消息。 当代码忙于调度生成的WM_TIMER
消息时,计时器可以在后台运行并再次设置标志,从而在下次抽取消息队列时生成新的WM_TIMER
消息。 因此,在回调中直接或通过模式对话框抽取消息时要小心,因为这可能会导致计时器回调的递归调用,从而可能导致堆栈随着时间的推移溢出。 但是,如果您的消息泵送仅在主线程循环中,那么您会没事的。
只要只有一个用于处理消息的入口点,一次只能处理一条消息。 您可以通过在已经运行的事件处理程序中处理更多消息来搞砸事情,但不要这样做,您应该没问题。