2016-02-22 44 views
0

如果我使用SendMessage()从不同线程到一个接收器会发生什么?想象一下,接收者仍在处理来自Thread1的消息,并且Thread2发送另一个消息(使用SendMessage())的情况。接收端会发生什么?是否停止执行Message1,处理Message2,并在Message2返回Message1后返回?或者Message2等待Message1的结束?使用SendMessage()多线程

+0

如果代码进入可更改的等待状态(这将允许Message2进行处理),Message1将在该处理期间被抢占。所以消息处理的顺序和原子性不能保证。 –

+1

当线程调用消息处理函数时,调度第二条消息。 –

回答

3

的基本规则是:唯一的时间线程分派跨线程发送的消息是,要求该线程的消息检索功能(GetMessagePeekMessage等)时。消息检索函数首先检查任何跨线程发送的消息,一个接一个地发送消息,然后继续从线程的消息队列中检索消息。

这具有2个后果:

  • 跨线程发送的消息被分派,当接收线程没有处理1)任何排队的消息。
  • 发送跨线程发送的消息,当接收线程不处理时1)任何其他跨线程发送的消息。

在您的具体示例中,接收方将继续处理Message1直到完成,然后继续在下一次调用Message2时调用Message2 retrieval函数。

这条规则有一个值得注意的例外:等待SendMessage返回的线程可以调度进入的跨线程发送的消息2)。这意味着有可能重新进入。再次举一个例子,假设Message1在某个点的消息处理程序调用SendMessage,很可能是在Message1继续处理之前分派Message2。

概括起来:

  • 跨线程发送的邮件接收线程连续调度。
  • 线程分派跨线程发送的消息时,有几个明确定义的时间。
  • 虽然跨线程发送的消息永远不会并发处理,但没有原子性规则;准备重新入住。


1)假设主叫的消息检索功能不正常的消息处理的一部分。
2)有关为什么会出现这种情况的详细信息,请参见 When can a thread receive window messages?

1

我假定问题是关于消息被发送到特定的窗口,即非NULL或HWND_BROADCAST的HWND,并且该窗口属于同一进程的线程。

在这种情况下,创建目标窗口的线程将在下次使用包含给定窗口的过滤器调用GetMessage时接收消息。发送线程将被阻塞,直到接收线程实际完成消息的处理。

如果在处理来自Thread1的消息时,接收线程再次调用GetMessage/DispatchMessage,那么任何待处理的消息(包括可能由Thread2发送的消息)将在该点处理,则控制将返回到处理消息来自Thread1。

从文档的SendMessage function

如果指定的窗口是通过调用线程创建的窗口过程立即作为子程序调用。如果指定的窗口是由不同的线程创建的,则系统切换到该线程并调用相应的窗口过程。仅当接收线程执行消息检索代码时才处理线程之间发送的消息。发送线程被阻塞,直到接收线程处理消息。

+0

我一直发现这个'切换到那个线程'声明有争议。事实是,它没有:它从事帽子接下来描述,这不是任何意义上的线程切换,而是某种类型的块和帖子。 – EJP

+0

@EJP对,就像措辞那样有点误导,最终效果就是你所描述的。 FWIW的引用直接来自官方的MSDN文档,并且(在快速检查中)至少自2001年以来没有改变。 – dxiv