PostMessage:未收到邮件

时间:2018-10-10 16:31:48

标签: c++ windows multithreading winapi

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

由于在某些情况下存在模态消息泵,所以我已经找到了很多解释,说明如果我在消息泵中执行了一些时髦的操作会如何发生,但是我并没有做任何时髦的事情。 / p>

我认为(但想确认)我的问题是由于在UI线程的生命周期中过早调用PostMessage所致。我的WinMain调用CreateWindowEx创建其主窗口,该窗口的WM_CREATE处理程序间接启动后台线程,该线程将相当快地使用主窗口的HWND调用PostMessage,甚至可能在WM_CREATE处理程序完成之前,很可能在WinMain的消息泵之前开始。

即使PostMessage返回成功,在这种情况下是否有可能丢失某些消息?在测试中,我确定在工作线程中调用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 个答案:

答案 0 :(得分:1)

  

由于在某些情况下存在模态消息泵,所以我已经找到了很多解释,说明如果我在消息泵中执行了一些时髦的操作会如何发生,但是我并没有做任何时髦的事情。 / p>

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

  

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

如果是这种情况,PostMessage()只会失败,但是您已经排除了这种情况。线程一旦调用任何user32.dll函数,即会创建消息队列,并且即使没有立即轮询队列也可以开始接收消息。

  

即使PostMessage返回成功,在这种情况下是否有可能会丢失一些消息?

不。发生了其他事情。您的消息循环错误地过滤了消息,或者格式错误的模式循环丢弃了消息,或者您只是在错误的HWND上发布消息。很难说,因为您没有显示任何代码。

  

在测试中,我确定在工作线程中调用PostMessage之前添加一个小的延迟(Sleep(50))足以防止任何消息丢失。

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

另一方面,线程如何知道要发布到哪个HWND?您的WM_CREATE处理程序是将其hwnd参数传递给线程,还是线程依赖于HWND返回的CreateWindowEx()?在后一种情况下,如果PostMessage()CreateWindowEx()退出之前被调用,则会失败。除非您接收的HWND变量最初未初始化,并且包含一个随机的非null值,PostMessage()将该变量解释为系统上其他位置的有效HWND