如何通知 CDialog 对象有关来自另一个线程的已完成任务?

Posted

技术标签:

【中文标题】如何通知 CDialog 对象有关来自另一个线程的已完成任务?【英文标题】:How to inform a CDialog Object about a finished task from another thread? 【发布时间】:2011-07-26 17:49:05 【问题描述】:

我有一个长时间运行的任务和一个对话框,通知用户此任务正在运行。任务完成后,对话框会通知用户。

我想在使用AfxBeginThread 创建的工作线程中启动任务,当任务完成后,我将用户消息WM_APP + 1PostMessage 发布到对话框。显然PostMessage 只能在同一个线程中使用,因此我尝试了PostThreadMessage,但在我的对话框中使用ON_THREAD_MESSAGE 时出现编译器错误。

现在我不知道如何继续。你有什么建议吗?

谢谢!

【问题讨论】:

【参考方案1】:

你可以使用PostMessage(),它会起作用的。 gui 线程将处理该消息。

我相信PostMessage 的文档很清楚:

在 与相关联的消息队列 创建指定的线程 窗口并返回而无需等待 处理消息的线程。

因此,如果工作人员将消息放入窗口的消息队列中, 创建窗口的线程将处理该消息。 在您的情况下,它是主(或 gui)线程。

【讨论】:

我错了,PostMessage 工作正常。问题是,我将一个 NULL 窗口句柄传递给 PostMessage。在创建对话框之前,我调用了GetSafeHwnd。谢谢你的回答,我找错方向了。【参考方案2】:

PostMessage()SendMessage() 都以异步或同步方式将消息传递到窗口句柄。

窗口句柄具有线程亲和性。这意味着任何与窗口句柄交互的代码都必须从拥有窗口的线程运行,也就是创建窗口的线程。

PostMessage()SendMessage() 通过确保在处理消息时由拥有窗口的线程处理来处理这个问题。

对于PostMessage(),这是一项简单的任务。每个线程都有自己的个人消息队列。当您调用PostMessage() 时,系统只需将消息放在属于拥有该窗口的线程的消息队列中。然后在线程抽出其消息队列的某个时间点处理该消息。

对于SendMessage(),更难安排消息由正确的线程处理。如果您从拥有窗口的线程调用SendMessage(),则直接调用窗口过程。否则系统会通知另一个线程需要运行同步消息然后阻塞。另一个线程,即拥有窗口的线程,仅在进行某些检测到消息正在等待的事实的系统调用时才处理该消息。这意味着对SendMessage() 的跨线程调用可能会导致性能问题。

【讨论】:

以上是关于如何通知 CDialog 对象有关来自另一个线程的已完成任务?的主要内容,如果未能解决你的问题,请参考以下文章

如何通知多线程应用程序中的特定线程

线程 等待/通知机制

什么模式或过程通知多个系统有关另一个系统的变化

来自另一个片段的 Snackbar 回调

如何在另一个更改通知程序类提供程序中使用来自一个更改通知程序类的方法

通知 ios 应用程序有关来自 SDK 的事件的理想方式