【问题标题】:Is it possible to share the same message queue between two threads?是否可以在两个线程之间共享相同的消息队列?
【发布时间】:2016-03-10 08:33:21
【问题描述】:

我想做的是让一个线程等待消息(WaitMessage),另一个线程处理应用程序的逻辑。第一个线程会在每条消息上醒来,以某种方式将此事件通知给另一个线程,再次进入睡眠状态,等等。这可能吗?

更新

考虑以下情况。我们有一个 GUI 线程,这个线程忙于长时间的计算。如果没有其他线程,则别无选择,只能不时检查新消息。否则,GUI 将在长时间计算期间变得无响应。现在我的系统使用这种“轮询”方法(它有一个不时检查消息队列的线程。)但是,我想知道这个其他解决方案是否可行:让另一个线程在 OS 消息队列上等待的 GUI,以便当 Windows 消息到达时,该线程将唤醒并告诉其他人有关该消息的信息。请注意,我不是在问如何在线程之间传递消息,而是第二个线程是否有可能等待操作系统消息到达第一个线程的队列。

我还应该补充一点,我不能有两个不同的线程,一个用于 GUI,另一个用于计算,因为我正在处理的系统是一个虚拟机,其上运行的 Smalltalk 图像不是线程安全的.这就是为什么拥有一个只发出新操作系统消息信号的线程将是理想的解决方案(如果可能的话)。

【问题讨论】:

  • 这样做有什么意义?那只会使您的程序更复杂,更慢。它不能带来任何好处。
  • @DavidHeffernan 简短的回答是:确保应用程序在忙于一些冗长的计算时也能响应;另外,我宁愿避免拉事件。为什么你认为等待线程会减慢执行速度?
  • 不要将消息发送到 GUI 线程
  • 你真的需要将你的长计算移动到不同的线程,它们一开始就不属于 GUI 线程。让 GUI 线程管理 GUI 和服务消息,在另一个线程中执行任何长时间运行的事情。如果你不能这样做,因为你的库不是线程安全的,那么你有 4 个选项 - 1)找到一个线程安全的库,2)让计算定期轮询消息队列,3)将计算分解成小块可以通过向自己发布消息来触发,或者 4) 将库移动到与您的主应用程序通信的单独进程。
  • 一个线程不可能等待和服务另一个线程的消息队列。

标签: windows multithreading winapi


【解决方案1】:

这取决于第一个线程收到消息后第二个线程需要做什么。

如果第二个线程只需要知道第一个线程收到消息,第一个线程可以使用SetEvent()PulseEvent() 发出Event object 信号,第二个线程可以使用WaitForSingleObject() 等待该事件。

如果第二个线程需要来自第一个线程的数据,它可以使用I/O Completion Port。第一个线程可以将数据包装在一个动态分配的结构中并使用PostQueuedCompletionStatus() 将其发布到端口,第二个线程可以使用GetQueuedCompletionStatus() 等待数据,然后在使用完成后释放它。

更新:根据您提供的新信息,一个线程不可能等待或服务另一个线程的消息队列。只有创建并拥有队列的线程才能从其队列中轮询消息。每个线程都有自己的消息队列。

您确实需要将长时间计算移至不同的线程,它们一开始就不属于 GUI 线程。让 GUI 线程管理 GUI 和服务消息,在另一个线程中执行任何长时间运行的事情。

如果您因为选择的库不是线程安全的而无法做到这一点,那么您有 4 个选项:

  1. 找到另一个线程安全的库。

  2. 在 GUI 线程中运行时,让计算定期轮询消息队列。

  3. 将计算分解为可由 GUI 线程向其自身发布消息触发的小块。发布消息并返回消息循环。收到消息后,做一点工作,发布下一条消息,返回消息循环。根据需要重复,直到工作完成。这允许 GUI 线程在每个计算步骤之间继续为消息队列提供服务。

  4. 将库移动到一个单独的进程,该进程会根据需要与您的主应用程序进行通信。

【讨论】:

  • 谢谢雷米。不幸的是,第二个线程忙于长时间的计算,因此不能Wait。它唯一能做的就是足够频繁地检查第一个线程是否更改了一个全局标志,表明队列中有新消息。
  • 那有什么问题呢?第二个线程将在安全的情况下处理标志,当它决定从当前正在做的事情中休息一下以做其他事情时。根据您的描述,这是非常好的解决方案。计算属于一个单独的线程,而不是 GUI 线程。
  • “一个线程不可能等待或服务另一个线程的消息队列” 这不正是 AttachThreadInput 所做的吗? (我并不是说这是一个好主意。我只是想理解这个断言。最好的方法是按照您的建议在非 GUI 线程上进行长时间计算。)
  • 不,这不是AttachThreadInput() 所做的。它允许两个线程共享同一个输入队列(用于处理键盘焦点等),而不是同一个消息队列。它们是有区别的。 Raymond Chen 的博客有几篇关于(错误)使用AttachThreadInput() 的危险的帖子。
猜你喜欢
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 2021-03-03
  • 1970-01-01
  • 2012-12-25
相关资源
最近更新 更多