Epr*_*pro 9 c++ winapi multithreading message-loop
最近我尝试在自己的线程中放置一个窗口的消息循环,我想知道为什么它从未收到任何消息,但我已经知道Windows将消息发布到创建窗口的线程.如何在一个线程中创建一个窗口并导致另一个线程接收该窗口的消息?我已经看过PostThreadMessage函数,但我相信它还需要创建窗口的线程来监听消息,这正是我试图避免的,所以这个函数不是我需要的.
这似乎是一个常见的问题,我花了很多时间谷歌搜索答案,但我找不到一个.
Windows消息泵实际上只是一个while循环,它使用PeekMessage()和调用你的Windows WndProc函数从队列中选择消息.还有一点比这更多,但这是基本的操作.
因此,while循环运行的任何线程都是您的窗口可以"运行"的唯一线程.这就是我所见过的每个Windows应用程序的构建方式.
但是我曾经想过,经过大量的努力,应该可以在多个线程中构建一个带有窗口的Windows应用程序.我没有任何代码可以告诉你,因为我考虑过这个问题已经很久了,但我考虑了两种方法:
在主线程中保留一个消息泵.但是修改消息泵代码,以便在while它QueueUserAPC根据特定HWND运行的线程将消息分派给工作线程.为此需要查找映射,这可能是计算上昂贵的.
在工作线程中创建一个全新的消息泵.您必须编写所有while代码,但这很简单,Petzold的经典书籍 将为您提供执行此操作所需的所有工具.
请注意,对于我能想到的任何应用程序,从架构的角度来看,这种方法没有任何意义.如果您合理地构建应用程序,则根本不需要Windows在多个线程中运行.窗口处理发生在一个线程中,操作发生在另一个(或许多)中.然而,我有一个有趣的研究领域,这就是我走这条道路的原因.长话短说,我几乎可以肯定你不需要这样做而且不应该这样做 - 但这可能就是你怎么做的.
这是不可能的.每个窗口都属于创建它的线程,并且无法传输所有权.
这不是将您的消息泵放在另一个线程中的问题.每个线程都有自己的消息队列.当您向窗口发送或发送消息时,操作系统会检查哪个线程拥有该窗口并将消息定向到该线程的消息队列.线程无法读取任何消息队列但是它们自己,所以你不能让一个线程处理另一个线程的窗口的消息.
您可以将消息重新发送到另一个线程,就像John的答案中的第一个想法一样,但作为一个通用的消息处理程序,它将变得比它的价值更复杂.许多消息用于修改窗口的状态,但除了窗口自己的线程外,您无法修改状态.发送一些消息的目的是获取有意义的返回值,但是在处理消息之前您无法知道要返回什么,因此您必须阻塞,等待工作线程处理消息.
你最好找出一小组真正可以卸载到工作线程并专门处理它们的消息.一旦你这样做,你就不会有一个窗口,其消息在不同的线程中处理; 你只需要一个普通的工作线程,理解它就不那么容易混淆了.
如果发送到您的窗口的消息需要大量时间来处理,但发送者要么不需要知道结果,要么在完成处理之前知道结果,那么您可以通过调用来提前响应ReplyMessage.这让发送线程继续运行,而你的窗口的线程做了额外的工作.