迥异和诡异的SendMessage和PostMessage
1 故障现象
故障现象1:能够收到SendMessage()发出的消息,但收不到PostMessage()发出的消息。
故障现象2:能够收到PostMessage()发出的消息,但收不到SendMessage()发出的消息。
2 两个比喻
从发送端来说:
SendMessage()好比电信系统提供通话服务。
如果对方占线,立即返回。
如果对方不占线,就保持呼叫→接收端接听→通话→挂断。在挂断之前,发送端处于阻塞状态,不可以干别的事。
PostMessage()好比电子邮件系统提供电子邮件服务。
发送端把邮件交给电子邮件系统,然后立即返回,就可以干别的事了。
电子邮件系统将邮件放在队列缓存区中,缓慢地将邮件发送到接收端的邮箱里。
从接收端来说(!!! 关键 关键 关键 !!!):
要接收SendMessage()的消息,必须用手机接听,到邮箱里无法接收此类消息。
要接收PostMessage()的消息,必须到邮箱里接收,用手机无法接听此类消息。
1 技术原理
在本文中:
把SendMessage()发送的消息成为立即消息。
把PostMessage()发送的消息成为延迟消息。
在计算机系统里,立即消息和延迟消息分别使用完全不同的途径发送消息,必须采用相匹配的、完全不同的接收方法才能收到消息。
1.1 立即消息的收发
为了接收并处理立即消息,接收端应用程序必须准备一张(消息,处理函数)映射表,如下表所示:
消息 | 处理函数 |
WM_USER + 1 | OnWmUser_1 |
WM_USER + 2 | OnWmUser_2 |
… | … |
WM_USER + n | OnWmUser_n |
立即消息的发送与接收的协作流程如下表:
发送端应用程序 | 操作系统 | 接收端应用程序 (消息处理总入口函数) |
发送消息 |
|
|
| 阻塞发送端应用程序 |
|
| 调用接收端应用程序的消息处理总入口函数 |
|
|
| 在(消息,处理函数)映射表中搜索与消息相匹配的处理函数,立即调用处理函数。 |
|
| 向操作系统返回处理结果 |
| 向发送端应用程序返回处理结果 |
|
| 解除阻塞发送端应用程序 |
|
接收消息处理结果 |
|
|
继续其它事务 |