WinAPI 的 ::WaitMessage 阻止WM_TIMER来



在我看来,我遇到了WinAPI的奇怪行为。在我的程序中,我正在为窗口设置一个计时器

::SetTimer(window_handle, timer_id, 10, NULL);

并在我的窗口中处理WM_TIMER消息。为了减少所需的 CPU 时间,我还在消息泵中使用了 ::WaitMessage 函数。现在事实证明,只要我在那里有::WaitMessage功能,WM_TIMER消息就会在一段时间后停止出现。如果我从我的消息泵中删除它,一切按预期工作正常。

现在我想知道我是否设置了错误的计时器,或者这是否是::WaitMessage的标准行为。搜索MSDN和网络并没有让我知道为什么会这样。

这是我使用的消息泵:

while(true) {
    if(GetMessage(&msg, _window_handle, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    } else { 
        return 0; 
    }
    WaitMessage();
}

希望有人能为我澄清这一点。

是的,这将随机无法处理更多的计时器消息。 对于 WaitMessage() 来说,一个非常硬的规则是,在调用消息队列之前,它应该是的。 如果它不为空,则队列中剩余的任何消息都将标记为"已见",WaitMessage() 会忽略它们。

因此,失败的情况是队列中有两条消息,例如鼠标消息和计时器消息。 您收到鼠标消息,但留下计时器消息。 不会生成其他计时器消息,因为您尚未处理挂起的计时器消息。 GetMessage + WaitMessage 的组合非常麻烦,您必须使用 PeekMessage 代替。

只需删除 WaitMessage(),它在这里没有任何用处。

除了Hans Passant所说的之外,你还应该改写代码。 WaitMessage不能很好地与GetMessage配合使用,请改用PeekMessage,并仅在备用代码路径(else)中保留WaitMessage,如下所示:

while( true )
{
    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    else
    {
        WaitMessage();
    }
}

WaitMessage允许线程休眠,直到消息进入队列。

相关内容

  • 没有找到相关文章

最新更新