发布消息:未收到消息

PostMessage: Messages not received

本文关键字:消息 布消息      更新时间:2023-10-16

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

我已经找到了许多解释,说明如果我在我的消息泵中做了一些时髦的事情,这会发生什么,因为在某些情况下存在模态消息泵,但我没有做任何时髦的事情。

我认为(但希望确认(我的问题是由于在 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) ;
}
}

我已经找到了很多解释,如果我在我的消息泵中做了一些时髦的事情,由于在某些情况下存在模态消息泵,这种情况是如何发生的,但我没有做任何时髦的事情。

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

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

如果是这样的话,PostMessage()会失败,但你已经排除了这一点。 只要线程调用任何user32.dll函数,消息队列就会创建并可以开始接收消息,即使队列没有立即轮询也是如此。

在这种情况下,

即使PostMessage返回成功,是否有可能/可能丢失某些消息?

不。其他事情正在发生。要么是消息循环过滤不正确,要么是格式错误的模式循环丢弃了消息,要么只是发布到错误的HWND。很难说,因为你没有显示任何代码。

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

在这 50 毫秒内,您的主线程通常在做什么?听起来您的 UI 代码中的某些内容在此期间正在接收和丢弃您发布的消息。

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