代码之家  ›  专栏  ›  技术社区  ›  Chris Long

PostMessage:未收到消息

  •  -2
  • Chris Long  · 技术社区  · 6 年前

    我正在寻找一个问题的一些反馈,我可以解决,但想更好地理解。我有一些多线程代码,其中工作线程使用win32api PostMessage函数将消息发布到主UI线程以更新TreeView。尽管我的日志显示PostMessage已成功返回,但有些已发布的消息有时无法通过UI线程的消息泵显示。

    我认为(但希望确认)我的问题是由于在UI线程的生命周期中过早调用PostMessage造成的。我的WinMain调用CreateWindowEx来创建它的主窗口,而该窗口的WM\u create处理程序间接启动后台线程,这些线程将相当快地使用主窗口的HWND调用PostMessage,甚至可能在WM\u create处理程序完成之前,很可能在WinMain的消息泵启动之前。

    在这种情况下,即使PostMessage返回success,某些消息是否可能/可能会丢失?在测试中,我已经确定在worker线程调用PostMessage之前在它中添加一个小的延迟(Sleep(50))就足以防止任何消息丢失。然而,我不相信这是解决根本问题,所以想知道我是否需要继续挖掘。

    我所有的代码中只有一个消息循环,除了调用通常的TranslateAccelerator等,它没有做任何异常的事情:

     // Enter the message loop
     while (GetMessage (&msg, NULL, 0, 0)) {
       if (!TranslateMDISysAccel(hwndClient, &msg) && !TranslateAccelerator (hwndFrame, hAccel, &msg)) {
         TranslateMessage (&msg) ;
         DispatchMessage (&msg) ;
       }
     }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Remy Lebeau    6 年前

    我已经找到了很多关于如果我在我的消息泵中做了一些令人毛骨悚然的事情会发生这种情况的解释,因为在某些情况下存在一个模态消息泵,但是我没有做任何令人毛骨悚然的事情。

    模态循环不会丢弃窗口消息,除非它们编码错误,并且不会将未知消息传递给 TranslateMessage() / DispatchMessage() 就像他们应该的那样。

    我认为(但希望确认)我的问题是由于在UI线程的生命周期中过早调用PostMessage造成的。

    PostMessage() 但你已经排除了这个可能性。一旦线程调用 user32.dll 函数,消息队列被创建并可以开始接收消息,即使队列没有立即轮询。

    在这种情况下,即使PostMessage返回success,某些消息是否可能/可能会丢失?

    不,还有别的事。要么您的消息循环过滤错误的消息,要么格式错误的模式循环丢弃消息,要么您只是发布到错误的位置 HWND . 很难说,因为您没有显示任何代码。

    在这50毫秒内,你的主线程通常在做什么?听起来你的UI代码中有东西在这段时间内接收和丢弃你发布的消息。

    另一方面,线程如何知道 投递到?是你的 WM_CREATE hwnd HWND公司 退回人 CreateWindowEx() ? 在后一种情况下, PostMessage() 如果之前调用,则应该失败 CreateWindowEx() 出口。除非你收到 变量最初未初始化,并且包含一个随机的非空值 PostMessage() 解释为有效的 HWND公司 在系统的其他地方。