【问题标题】:Why is SendMessage designed to behave different in a window's procedure than in worker threads?为什么 SendMessage 在窗口过程中的行为与在工作线程中的行为不同?
【发布时间】:2014-04-09 10:53:56
【问题描述】:

首先我想请你不要误解这个问题。我不是在问 SendMessage 是如何工作的,而是为什么它被设计成它的工作方式。基本上,我想知道为什么不能直接从工作线程调用窗口过程,就像从窗口线程调用一样,而不是将消息泵入消息队列?

在工作线程中的一个非常简单的情况下,我可以这样做:

WndProc(hWnd,MY_MESSAGE,wParam,lParam);

代替:

SendMessage(hWnd,MY_MESSAGE,wParam,lParam);

并立即得到响应。直接调用 WndProc 有什么缺点吗?

我可以理解,当您想向另一个进程拥有的窗口发送消息时,事情会变得更加复杂,但不能存在类似 SendMessage 的函数,该函数在工作线程中工作相同,例如在窗口线程?不存在的背后有什么原因吗?预先感谢您的任何解释。

【问题讨论】:

  • 这归结为窗口与创建它们的线程有关联。所以这种行为是使系统线程安全的一部分。
  • 编写这样的代码没有任何意义。您改为重构窗口过程并将 case: 语句中的代码移动到单独的函数中。并调用该函数。 SendMessage() 的要点是你不知道窗口的实现细节。在这种情况下,从另一个线程调用它是一个很好的方法来打断你的腿。总是有太多的代码挂在消息管道上,这完全是线程不安全的。像反恶意软件、可访问性、Windows 挂钩等。

标签: windows winapi


【解决方案1】:

窗口过程的编写者希望所有调用都在一个线程上进行。通过使用SendMessage,可以将消息放置在(线程安全的)队列中。单个线程可以将消息从队列中取出并传递给窗口过程。

缺点是从另一个线程调用WndProc 会引入竞争条件。某些 UI 对象具有线程关联性。如果不尊重这一点(例如,通过从另一个线程调用 WndProc),那么这可能会导致问题。设备上下文就是一个例子。根据Raymond Chen

Window 对象具有线程亲和性。创建窗口的线程是与窗口密不可分的线程。非正式地,有人说线程“拥有”窗口。消息仅在拥有它的线程上发送到窗口过程,一般来说,对窗口的修改只能从拥有它的线程中进行。尽管窗口管理器允许任何线程访问诸如窗口属性、样式和其他属性(如窗口过程)之类的东西,并且从窗口管理器的角度来看,此类访问是线程安全的,但通常应该限制加载-修改-写入序列到所有者线程。否则你会遇到竞争条件......

【讨论】:

  • Windows GUI 当然是线程安全的。您需要遵循与线程关联性相关的规则。整个 Windows API 都是线程安全的。再次提供您遵循线程规则。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 2018-12-15
  • 1970-01-01
相关资源
最近更新 更多