【发布时间】:2012-06-27 12:41:26
【问题描述】:
当一个窗口被销毁而仍有未处理的消息时会发生什么?
考虑以下场景:
共有三个线程,A、B 和 C。线程 C 拥有一个窗口。
线程 A 和 B 使用SendMessage 将消息发布到窗口。来自 A 的消息首先到达。当 C 处理来自 A 的消息时,它使用 DestroyWindow 销毁它的窗口。
来自线程 B 的消息会发生什么?线程B对SendMessage的调用是否返回?
这在内部是如何工作的?
【问题讨论】:
当一个窗口被销毁而仍有未处理的消息时会发生什么?
考虑以下场景:
共有三个线程,A、B 和 C。线程 C 拥有一个窗口。
线程 A 和 B 使用SendMessage 将消息发布到窗口。来自 A 的消息首先到达。当 C 处理来自 A 的消息时,它使用 DestroyWindow 销毁它的窗口。
来自线程 B 的消息会发生什么?线程B对SendMessage的调用是否返回?
这在内部是如何工作的?
【问题讨论】:
原则上,您提议做的事情并不安全。线程 C 无法保证线程 B 已经发送了消息;如果窗口在线程 B 发送消息之前被销毁,并且窗口句柄恰好在此期间被重用,则线程 B 可能最终将消息发送到错误的窗口,该窗口可能位于不同的应用程序中。
最佳做法是确保在调用 DestroyWindow 之前通知所有线程特定窗口句柄已失效。
但是,实际上,在错误的时间重复使用句柄的风险非常低。如果提前通知其他线程是不合理的,那么您不太可能因此陷入困境。我相信 kicsit 断言消息不会最终在线程 C 的消息队列中等待是正确的,尽管据我所知文档并没有明确承诺这一点。
【讨论】:
根据MSDN,DestroyWindow“[...],刷新线程消息队列,[...]”。我不确定这是否意味着处理消息或转储它们,所以我尝试了。结果是后者:所有未决的已发布消息都从队列中删除并被忽略。至于非排队消息:在我的测试中,待处理的SendMessage 调用返回并将最后一个错误设置为ERROR_INVALID_PARAMETER - 87 (0x57)。
【讨论】: