首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一个线程何时才能收到Window消息?

你(可能)不知道的

和Windows消息系统打过交道的人都会知道:GetMessage和PeekMessage这两个API会从窗口的消息队列中检索消息,这些消息时由DispatchMessage分发到窗口的。

大部分人也知道:GetMessage和PeekMessage也会自己分发不进入消息队列的消息。(所有挂起的非队列消息将会被分发,然后只有第一个进入队列的消息会被返回)

但是大多数人不知道的是:SendMessage也会分发消息。

如果线程T1发送消息给一个属于线程T2的窗口,则T1线程会进入睡眠状态直到接收消息的线程处理了这个消息。但是,如果有其他人也发送一个消息到线程T1,则T1则会被唤醒并处理消息,然后会返回到睡眠状态。

为什么这样设计?

Well,当两个线程T1和T2一起协同工作的时候,很有可能发生的场景是:线程T1向线程T2发送消息,同时,当线程T2返回响应给T1之前它就发送消息给T1。因此,线程T1必须准备好接收线程T2发来的消息。

举个例子,线程T1可能发送一个消息,说:”请告诉你所知道的关于X的一切。” 线程T2接着会发送一个消息给线程T1,说:”这个是一个X”,然后继续发送另一个消息:说:”这个是另一个X”,以此类推,直到它将所有关于X的信息告诉给线程T1。

这个时候,线程T1在原始消息返回的时候,它就知道已经收到了所有线程T2发来的关于X的信息。这个循环往复的过程,就是DDE服务的运行原理。

另外一个例子

线程T1发送一个消息给T2,然后线程T2在完成消息的处理之前,还需要请求线程T1给予某种帮助,这其实没有听起来那么奇怪。因为你也会做类似的事情,具体来说,就是当你通过发送消息给控件来响应WM_NOTIFY消息的场景,控件就是WM_NOTIFY消息的发送者。(举个例子,你可能通过向控件发送LVM_GETITEM以获取被激活的条目信息,来响应收到的LVN_ITEMACTIVATE通知消息)

所以,请记住:当你发送消息的时候,就会存在潜在的可重入的可能性。

总结

线程的同步和协同工作,看起来还比较容易操作,但是真正要做到万无一失,还是得深入理解其背后的原理。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。

本文来自:《When can a thread receive window messages?》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210401A0E58S00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券