响应性地检查两个队列而不锁定CPU
responsively checking two queues without pegging CPU
我有一个线程池系统,它使用消息传递来组织事件,我还使用Windows API,它也做一些消息传递。因此,本质上我需要使用在不阻塞的情况下检查消息存在的功能。如果我在检查任一队列时阻止(如果我使用GetMessage
,我认为它会阻止(,我可能会错过另一个队列上的任何传入消息。
我知道的第一个解决方案是在我对两个队列进行窥视的循环中,在某个地方Sleep
几毫秒。
我可以想到的另一种方法是有一个额外的线程,这样我现在就可以为正在收听的每个循环都有一个线程。我让它不负责运行windows消息循环之外的任何事情,然后用它来处理任何事件,并将其转发到我自己的消息队列中,以便处理该事件。但如果Windows专门将我感兴趣的消息发送到原始线程,这将不起作用。
还有其他好的解决方案吗?
您的要求有点不清楚,但我同意Windows消息队列很尴尬,因为只有一个线程可以等待它们。Windows将窗口绑定到线程,只有创建窗口的线程才能与之交互
如果您的线程池中有包含要处理的工作的用户定义消息,我建议您完全按照问题中的建议执行-使用一个线程处理所有Windows消息,(GetMessage((循环(,重新排队进入线程池输入队列的任何工作,并使用通常的翻译/调度机制处理"正常"Windows消息。
如果你需要更多帮助,你能更清楚地描述Windows消息和/或工作对象在你的系统中的流动吗?线程池的工作从哪里来以及如何传输还不清楚(如果被迫使用WMQ,我通常会在wParam/lParam中发布消息引用,但你的系统呢?(。
Rgds,Martin
通常情况下,线程池不会参与Windows消息循环,并且在没有工作的情况下无限期阻塞不仅是工作线程所允许的,甚至是所希望的。
实现线程池的最优雅的方法是使用完成端口,该线程池可以通过某种队列接收消息,这会自动使所有CPU核心保持繁忙,而且效率非常高
具有null句柄的CreateIoCompletionPort
将创建一个完成端口并返回句柄。作为NumberOfConcurrentThreads
传递零告诉操作系统保持尽可能多的线程运行,只要有可用的内核。
创建任意数量的工作线程(比您的核心多出几个(,并使用第一次调用返回的句柄创建CreateIoCompletionPort
。这将把工作进程绑定到这个完成端口。现在在每个工作进程上调用GetQueuedCompletionStatus
,INFINITE
超时,这将不确定地阻止它们。
制作一个struct
,它的第一个成员是OVERLAPPED,加上你想作为任务传递的任何数据(一些指向数据的指针,或任何东西(。
对于每个任务,设置一个消息结构,并将PostQueuedCompletionStatus
设置为完成端口句柄。在应用程序退出时,发布null。您可以使用dwNumberOfBytesTransferred
字段(和完成键(来传递一些附加信息。
现在,Windows将为您发布的每条消息唤醒一个线程,按后进先出的顺序,直到可用的内核数量。如果其中一个工作线程阻塞了IO,Windows将为另一个任务唤醒另一个工作进程(只要有工作要做,就让CPU保持忙碌(。
完成任务后,返回GetQueuedCompletionStatus
。
一种优雅地终止所有工作程序的方法是传递"传输的零字节",并让工作程序重新发布事件,如果遇到这种情况,则退出。
我不是windows队列方面的专家,但我几乎可以肯定,必须有一种异步事件驱动的消息传递机制。
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 提升消息队列 跨两个进程未接收
- C 将两个整数进入队列
- C++ std::队列推送弹出两个不同的对象获取第一个对象
- 两个提升的无锁队列会导致僵局
- 这两个优先级队列包装器有什么区别
- 通过使用两个不同的队列比较字符串
- 在 c++ 中退出具有三个线程的两个并发队列
- c++中相同指针的两个优先级队列
- 合并两个优先级队列
- 在c++中,在两个进程之间拥有无限对象队列的最佳方式
- 用两个堆栈实现队列——脱队列测试问题
- 在两个线程之间同步队列
- 由两个线程访问的共享队列的临界区代码是什么?
- 从相同的结构体以相反的顺序创建两个优先级队列
- 响应性地检查两个队列而不锁定CPU
- boost条件不在具有两个生产者和一个消费者的线程安全队列上工作
- 具有两个线程(生产者、消费者)的 STL 队列
- 合并两个std::队列