【发布时间】:2016-06-02 07:08:41
【问题描述】:
我想确认一下我认为是真的。当我使用 Windows SendMessage() 时,这是一个确定性调用,因为它将立即执行(在处理消息之前不会返回),而 PostMessage() 是非确定性的,因为它可以被任何其他消息抢占恰好在那个时间点在队列中(实际上它在到达消息循环之前不会被执行)。
这是一个公平的评估,还是我遗漏了什么?
【问题讨论】:
标签: windows message-queue
我想确认一下我认为是真的。当我使用 Windows SendMessage() 时,这是一个确定性调用,因为它将立即执行(在处理消息之前不会返回),而 PostMessage() 是非确定性的,因为它可以被任何其他消息抢占恰好在那个时间点在队列中(实际上它在到达消息循环之前不会被执行)。
这是一个公平的评估,还是我遗漏了什么?
【问题讨论】:
标签: windows message-queue
对于进程内调用来说基本上是这样。跨进程 SendMessage 的工作方式类似,但在接收进程调用 GetMessage(或其亲属)之前不会开始处理消息。
您的 UI 线程有一个类似于以下内容的消息泵:
while (GetMessage(&msg))
DispatchMessage(&msg);
PostMessage 使消息被放入消息队列。 GetMessage 从队列中移除最旧的消息 (FIFO*)。
DispatchMessage 导致与消息的目标窗口关联的 WndProc 与消息一起被调用。
SendMessage 基本上绕过了这条链,直接(或多或少)调用了 WndProc。
许多标准窗口消息会导致一系列 SendMessage 调用,其中发送一条消息发送另一条消息,后者发送另一条消息。该链通常被称为“当前调度”。如果您需要在链中处理您的消息,请使用 SendMessage。如果您需要在当前调度完成后对其进行处理,请使用 PostMessage。
您可以使用Spy++ 之类的工具来查看 Windows 消息传递的运行情况,或者调试您遇到的消息操作顺序问题。
[*] 它不是严格意义上的 FIFO 队列,因为某些类型的消息(即计时器、鼠标、键盘)实际上并没有发布到队列中,而是动态生成的。为简单起见,您可以将其视为 FIFO。
【讨论】: