在先前分派的消息回调完成之前触发消息时会发生什么?

时间:2012-09-24 19:21:55

标签: winapi win32gui

我花了一些时间试图研究一个确定的答案,但找不到可靠的来源。

我的情景相当简单。我有一个带有消息泵设置的线程,它正在处理来自计时器的重复事件。这是消息泵源:

// 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);
    }
}

如果TimerCallback超过500毫秒,计时器将再次触发其事件。由于回调正在与消息泵相同的线程上执行,我假设回调必须在消息泵处理下一个定时器消息之前完成。

这是对的吗?

2 个答案:

答案 0 :(得分:2)

SetTimer()是基于消息的计时器。当计时器过去时,它在消息队列中设置一个特殊标志。当您为新消息抽取队列时,如果已设置该标志并且其他更高优先级的消息未在队列中等待,则将创建WM_TIMER消息。当您的代码忙于调度生成的WM_TIMER消息时,计时器可以在后台运行并再次设置标志,在下次为消息抽取队列时生成新的WM_TIMER消息。因此,在回调内部直接或通过模态对话框时要小心泵送消息,因为这可能会导致计时器回调的递归调用,从而可能导致堆栈随时间溢出。但是如果你的消息只在你的主线程循环中,那么你会没事的。

答案 1 :(得分:1)

只要处理消息只有一个入口点,一次只能处理一条消息。你可以通过在已经运行的事件处理程序中处理更多消息来解决问题,但是不要这样做,你应该没事。