GetMessage超时

时间:2012-06-02 22:08:01

标签: c++ windows winapi

我有一个应用程序,第二个线程在循环中调用GetMessage()。在某些时候,第一个线程意识到用户想要退出应用程序并通知第二个线程它应该终止。由于第二个线程卡在GetMessage()上,程序永远不会退出。有没有办法等待超时的消息? 我也对其他想法持开放态度。

编辑:(其他说明)

第二个线程运行该代码片段:

while ( !m_quit && GetMessage( &msg, NULL, 0, 0 ) )
{
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}

第一个线程将m_quit设置为true。

5 个答案:

答案 0 :(得分:20)

未经测试,但您可以尝试使用MsgWaitForMultipleObjects函数而不需要任何对象。

MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLEVENTS);

如果if返回WAIT_TIMEOUT则超时,但如果返回WAIT_OBJECT_0,则可以致电GetMessage并保证不会被阻止。

但请注意以下事项:

  

如果在线程调用检查队列的函数后,如果消息队列中存在指定类型的未读输入,则MsgWaitForMultipleObjects不会返回。

因此,您必须确保上次调用任何消息函数时,队列中没有消息,否则您将遇到某种竞争条件。

可能您最好的选择是将GetMessage替换为:

if (MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLEVENTS) == WAIT_OBJECT_0)
{
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        //dispatch the message
    }
}

但正如我之前所说,我没有测试过,所以我不能确定它是否会起作用。

答案 1 :(得分:13)

最简单的方法是在致电UINT_PTR timerId=SetTimer(NULL, NULL, 1000, NULL)之前致电GetMessage。它会每秒向调用线程发送一条WM_TIMER消息,因此GetMessage将立即返回。然后,请致电KillTimer(NULL, timerId)取消它。

更新示例代码:

BOOL GetMessageWithTimeout(MSG *msg, UINT to)
{
    BOOL res;
    UINT_PTR timerId = SetTimer(NULL, NULL, to, NULL);
    res = GetMessage(msg);
    KillTimer(NULL, timerId);
    if (!res)
        return FALSE;
    if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == timerId)
        return FALSE; //TIMEOUT! You could call SetLastError() or something...
    return TRUE;
}

答案 2 :(得分:4)

您可以随时做的一件事就是向被阻止的线程发送一条用户定义的消息,该消息将导致它被唤醒,处理消息,然后返回到循环的顶部。实际上,最简单的方法是完全删除m_quit变量,而只是向主线程发送一条消息,说明“你现在需要退出。”

希望这有帮助!

答案 3 :(得分:3)

您应该可以使用PostThreadMessage向第二个帖子发送退出消息。

E.g。

PostThreadMessage(threadid, WM_QUIT, 0, 0);

您不需要在第二个帖子中阅读m_quit变量,但是您应该检查来自GetMessage的错误以及返回值FALSE/0,这是返回的内容如果下一条消息是退出消息。

答案 4 :(得分:-1)

是的。请尝试使用PeekMessage()。但我认为这不会解决问题。