使用 SendMessage() 多线程
Using SendMessage() Multi-threaded
如果我使用从不同线程到一个接收器的 SendMessage() 会怎样?想象一种情况,当接收方仍在处理来自线程 1 的消息时,线程 2 发送了另一条消息(使用 SendMessage())。接收端会发生什么?它是否停止执行 Message1,处理 Message2 并在 Message2 returns 完成后返回 Message1?还是 Message2 等待 Message1 结束?
我假设问题是关于发送到特定 window 的消息,即非 NULL 或 HWND_BROADCAST 的 HWND,并且 window 由属于同一个进程的线程。
在这种情况下,创建目标 window 的线程将在下次使用包含给定 window 的过滤器调用 GetMessage 时接收消息。发送线程将被阻塞,直到接收线程真正完成对消息的处理。
如果在处理来自 Thread1 的消息时,接收线程再次调用 GetMessage/DispatchMessage,那么任何未决消息(包括可能由 Thread2 发送的消息)都将在此时处理,然后控制将 return 到处理来自 Thread1 的消息。
来自 SendMessage function 的文档:
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.
基本规则是:线程调度跨线程发送的消息的唯一时间是在该线程上调用消息检索函数(GetMessage, PeekMessage 等)时。消息检索函数首先检查任何跨线程发送的消息,一个接一个地分派它们,然后继续从线程的消息队列中检索消息。
这有两个后果:
- 跨线程发送的消息在接收线程未处理时调度1)任何排队的消息。
- 跨线程发送的消息被分派,当接收线程不处理时1)任何其他跨线程发送的消息。
在您的特定示例中,接收方将继续处理 Message1 直到完成,并在下次调用消息检索函数时继续分派 Message2。
此规则有一个值得注意的例外:等待 SendMessage 到 return 的线程可以分派入站跨线程发送的消息2).这意味着存在重新进入的可能性。再次以您的示例为例,假设 Message1 的消息处理程序在某个时刻调用 SendMessage
,很可能是在继续处理 Message1 之前分派 Message2。
总结一下:
- 跨线程发送的消息在接收线程上连续分派。
- 线程调度跨线程发送的消息时,有几个明确定义的时间。
- 虽然跨线程发送的消息从不并发处理,但没有原子性规则;为重新进入做好准备。
1) 假设调用消息检索函数不是正常消息处理的一部分。
2) 请参阅 When can a thread receive window messages? 了解为什么会出现这种情况的详细信息。
如果我使用从不同线程到一个接收器的 SendMessage() 会怎样?想象一种情况,当接收方仍在处理来自线程 1 的消息时,线程 2 发送了另一条消息(使用 SendMessage())。接收端会发生什么?它是否停止执行 Message1,处理 Message2 并在 Message2 returns 完成后返回 Message1?还是 Message2 等待 Message1 结束?
我假设问题是关于发送到特定 window 的消息,即非 NULL 或 HWND_BROADCAST 的 HWND,并且 window 由属于同一个进程的线程。
在这种情况下,创建目标 window 的线程将在下次使用包含给定 window 的过滤器调用 GetMessage 时接收消息。发送线程将被阻塞,直到接收线程真正完成对消息的处理。
如果在处理来自 Thread1 的消息时,接收线程再次调用 GetMessage/DispatchMessage,那么任何未决消息(包括可能由 Thread2 发送的消息)都将在此时处理,然后控制将 return 到处理来自 Thread1 的消息。
来自 SendMessage function 的文档:
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.
基本规则是:线程调度跨线程发送的消息的唯一时间是在该线程上调用消息检索函数(GetMessage, PeekMessage 等)时。消息检索函数首先检查任何跨线程发送的消息,一个接一个地分派它们,然后继续从线程的消息队列中检索消息。
这有两个后果:
- 跨线程发送的消息在接收线程未处理时调度1)任何排队的消息。
- 跨线程发送的消息被分派,当接收线程不处理时1)任何其他跨线程发送的消息。
在您的特定示例中,接收方将继续处理 Message1 直到完成,并在下次调用消息检索函数时继续分派 Message2。
此规则有一个值得注意的例外:等待 SendMessage 到 return 的线程可以分派入站跨线程发送的消息2).这意味着存在重新进入的可能性。再次以您的示例为例,假设 Message1 的消息处理程序在某个时刻调用 SendMessage
,很可能是在继续处理 Message1 之前分派 Message2。
总结一下:
- 跨线程发送的消息在接收线程上连续分派。
- 线程调度跨线程发送的消息时,有几个明确定义的时间。
- 虽然跨线程发送的消息从不并发处理,但没有原子性规则;为重新进入做好准备。
1) 假设调用消息检索函数不是正常消息处理的一部分。
2) 请参阅 When can a thread receive window messages? 了解为什么会出现这种情况的详细信息。