MFC:从另一个线程调用 CWnd 方法是否安全?

MFC: Is it safe to call CWnd methods from another thread?

其实我有两个问题:

  1. 从工作线程调用 SendMessage 安全吗?
  2. 执行 CWnd 方法,例如 MessageBox,在幕后调用 API 函数 SendMessage

根据我的理解,当工作线程调用SendMessage时,它会将消息推入UI线程的消息队列中,并等待直到该消息被处理。在那种情况下,这样做是安全的。

我不太确定这个。如果我错了,请纠正我。

非常感谢。

------------------------更新-------------------- --------------

作为结论:

非常感谢大家。

Is it safe to call SendMessage from a worker thread?

是的。系统确保消息处理在接收线程上被序列化。跨线程发送消息时,发送方被阻塞,直到消息被处理。接收方在执行消息检索代码(GetMessagePeekMessage 等)时仅处理 cross-thread 发送的消息。已发送的消息永远不会 queued 在消息 queue 中。 SendMessage 的文档有更多详细信息。

Do CWnd methods, like MessageBox, call API function SendMessage behind the scene?

是的。首先,消息框将接收标准的 window 消息,例如 WM_CREATEWM_NCCREATE 作为对话构造的一部分。此外,对于拥有的 windows(如模态对话框),系统将向正在停用的 window 和正在激活的 window 发送 WM_ACTIVATE 消息。不过,我不确定为什么这很重要,或者你为什么特别问这个问题。

现在你标题中的问题:

Is it safe to call CWnd methods from another thread?

一般来说,不会。不过,这确实取决于成员。有些可以安全调用,有些则不能。特别是,所有修改 window 状态(内容、可见性、激活等)的方法只能从创建 window 的线程调用。如果调用不安全,系统仍将处于一致状态。但是,您的应用程序可能不是。

线程访问 UI 的 ONLY 方法是使用 SendMessagePostMessage.

考虑一台只有一个内核的机器,其中发生上下文切换并且您从工作线程直接访问 UI,您可能会破坏 UI 线程寄存器!

基本上每个 UI 框架都提供了一种机制(很多次是几种),用于从线程进行 UI 更改。例如 Android 提供 ASyncTaskHandler.