已销毁窗口的挂起消息会发生什么?

4
当窗口销毁时,如果仍有未处理的消息会发生什么情况?
考虑以下情况:
有三个线程A、B和C。线程C拥有一个窗口。
线程A和B使用SendMessage向窗口发送消息。来自A的消息首先到达。当C正在处理来自A的消息时,它使用DestroyWindow销毁了窗口。
线程B的消息会发生什么?线程B调用SendMessage会返回吗?
这在内部是如何工作的?
2个回答

1
根据MSDNDestroyWindow "[...],刷新线程消息队列[...]"。我不确定这是否意味着处理消息还是丢弃它们,所以我尝试了一下。结果证明是后者:所有待处理的已发布消息都将从队列中删除并被忽略。至于非排队消息:在我的测试中,待处理的SendMessage调用返回并将最后一个错误设置为ERROR_INVALID_PARAMETER - 87 (0x57)

有趣,但我不会依赖这种行为。很可能存在竞态条件,即结果很可能取决于三个线程被安排的确切顺序,因此它可能99.9%的时间做一件事情,而另外0.1%的时间则做另一件事情。 - Harry Johnston
现在我想起来,我的观点可能已经没有意义了;毕竟通过一个可能已经被销毁的窗口句柄发送消息本质上是无效的,不是吗? - Harry Johnston
https://dev59.com/kVrUa4cB1Zd3GeqPhz_U - Harry Johnston
DestroyWindow函数并不会清空所有消息,它只会清空与该窗口相关的消息。如果C拥有多个窗口,DestroyWindow将无法清空线程消息队列,只有特定窗口的消息才会被删除。因此,我认为MSDN的解释不够清晰。 - user738471

1
原则上,您提议的做法是不安全的。线程C无法保证线程B已经发送了消息;如果窗口在线程B发送消息之前被销毁,并且窗口句柄在此期间恰好被重用,线程B可能会将消息发送到错误的窗口,该窗口可能位于不同的应用程序中。
最佳实践是,在调用DestroyWindow之前,确保所有线程都已被告知特定窗口句柄已变为无效状态。
然而,实际上,句柄在恰好错误的时间被重用的风险非常低。如果事先通知其他线程不可行,则不太可能因此遇到麻烦。我相信kicsit正确地断言消息不会出现在线程C的消息队列中,尽管据我所知,文档并没有明确承诺这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接