我正在寻找有关我可以解决的问题的一些反馈,但希望更好地理解。我有一些多线程代码,其中工作线程使用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) ;
}
}
答案 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
。