【问题标题】:What happens to pending messages for a window that has been destroyed?已销毁的窗口的未决消息会发生什么情况?
【发布时间】:2012-06-27 12:41:26
【问题描述】:

当一个窗口被销毁而仍有未处理的消息时会发生什么?

考虑以下场景:

共有三个线程,A、B 和 C。线程 C 拥有一个窗口。

线程 A 和 B 使用SendMessage 将消息发布到窗口。来自 A 的消息首先到达。当 C 处理来自 A 的消息时,它使用 DestroyWindow 销毁它的窗口。

来自线程 B 的消息会发生什么?线程B对SendMessage的调用是否返回?

这在内部是如何工作的?

【问题讨论】:

    标签: windows message


    【解决方案1】:

    原则上,您提议做的事情并不安全。线程 C 无法保证线程 B 已经发送了消息;如果窗口在线程 B 发送消息之前被销毁,并且窗口句柄恰好在此期间被重用,则线程 B 可能最终将消息发送到错误的窗口,该窗口可能位于不同的应用程序中。

    最佳做法是确保在调用 DestroyWindow 之前通知所有线程特定窗口句柄已失效。

    但是,实际上,在错误的时间重复使用句柄的风险非常低。如果提前通知其他线程是不合理的,那么您不太可能因此陷入困境。我相信 kicsit 断言消息不会最终在线程 C 的消息队列中等待是正确的,尽管据我所知文档并没有明确承诺这一点。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 有趣,但我不会依赖这种行为。可能存在竞争条件,即结果很可能取决于调度三个线程的确切顺序,因此它可能在 99.9% 的时间里做一件事,而在另外 0.1% 的时间里做不同的事情。
      • 现在我想起来了,我的观点可能没有实际意义;确定通过可能已经被销毁的窗口句柄发送消息本质上是无效的吗?
      • DestroyWindow 不会转储所有消息。它只转储特定于该窗口的消息。如果假设 C 拥有多个窗口,则 DestroyWindow 不会刷新线程消息队列。只有特定的 Windows 消息被删除。所以我认为 MSDN 不清楚。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多