c++ - PostMessage:未收到消息
问题描述
我正在寻找一些关于我可以解决的问题的反馈,但想更好地理解。我有一些多线程代码,其中工作线程使用 Win32 API PostMessage 函数将消息发布到主 UI 线程以更新 TreeView。尽管我的日志显示 PostMessage 成功返回,但某些发布的消息有时无法通过 UI 线程的消息泵出现。
由于在某些情况下存在模态消息泵,我已经找到了许多关于如果我在消息泵中做了一些时髦的事情会发生这种情况的解释,但我没有做任何时髦的事情。
我认为(但想确认)我的问题是由于在 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
参数传递给线程,还是依赖于HWND
返回的线程CreateWindowEx()
?在后一种情况下,如果在退出PostMessage()
之前调用应该会失败。CreateWindowEx()
除非您的接收HWND
变量最初是未初始化的并且包含一个随机的非空值,该值被PostMessage()
解释为HWND
系统上其他地方的有效值。
推荐阅读
- pytest - 多线程 Pytest
- python - 如何使我的“标签”对象具有属性“获取”?
- math - 考虑到每个点都有自己的范围,尽可能多地散布点意味着什么?
- python - 在 python 中编码双变量分布的图形表示
- javascript - FlatList - 如何自动到顶部
- google-sheets - 如何将未结订单预期接收日期的第一个实例拉到不同的 Google 表中,比较零件清单
- arrays - Julia SharedArrays - 编写非位类型
- sql - 使用 Informix SQL 进行动态透视
- java - pom.xml 用于具有多个主类的单个 jar
- spring - 如果发生异常,如何禁用记录 Kafka 批处理中的所有消息?