当负责处理消息的线程挂起时会发生什么?

时间:2015-10-20 17:28:33

标签: winapi window message-queue hwnd

我有一个应用程序,其中一个DLL模块负责处理发布到其隐藏窗口的用户定义消息。假设负责处理这些消息的线程在处理其他任务时挂起,在此期间,如果消息被另一个低级别层发布到此窗口(使用PostMessage),发布的内容将会发生什么消息?

我的应用程序有时不会收到这些消息,而低级别层中的日志表明他们已发布消息但我的应用程序没有收到消息。我怀疑,由于线程繁忙或挂起,它将不会处理这些消息。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

简短的回答是,如果您使用隐藏窗口来处理来自系统和其他应用程序组件的消息,那么保持该消息泵运行并处理消息非常重要。如果你有一个长时间运行的任务会让你远离你的消息队列一段时间,那么正确的答案是将该任务传递给一个单独的线程。

更复杂的答案是可能发生了两个问题:

  1. 邮件队列已满。
  2. 未正确检查调用PostMessage的返回值。
  3. 第一个问题很简单。 PostMessage的文档非常清楚 1

      

    每个邮件队列的发布邮件数量限制为10,000。这个限制应该足够大。如果您的应用程序超出限制,则应重新设计它以避免消耗这么多系统资源。

    带回家的消息是,消息处理中涉及的线程应该在获取下一条消息以保持应用程序响应的行程之间尽可能少地执行,并防止浪费资源。

    您的代码中可能存在或可能不存在的第二个问题是需要检查PostMessage的返回值。文档说明了,但TL; DR;如果返回值为0,则调用失败。如果且仅当 2 返回值为0时,请调用GetLastError以获取错误代码。如果错误为ERROR_NOT_ENOUGH_QUOTA,则队列已满。以代码段形式:

    if (PostMessage(hwnd, msg, wParam, lParam) == 0)
    {
        if (GetLastError() == ERROR_NOT_ENOUGH_QUOTA)
        {
            cout << "Message Queue is Full" << endl;
        }
    }
    

    1 通常MSDN在说不应该做的事情时并不那么强大。如果对某些事情如此明确,那么最好遵循这些建议。 (另外值得一提的是:增加配额将成为解决当地问题的全球解决方案。)

    2 当一个函数成功,或者被调用的函数不是GetLastError时,调用SetLastError是一个令人震惊的常见错误。