【问题标题】:How to make proper sequential async message processing in Windows?如何在 Windows 中进行正确的顺序异步消息处理?
【发布时间】:2012-10-04 02:58:25
【问题描述】:

我有一个 Windows 应用程序需要非常快速地处理所有传入的消息,否则我想它会严重削弱系统性能。我想到的是一种为每条消息生成和加入线程的方法,以便按顺序处理它们。但是这种方法有一个严重的问题:当我产生线程并尝试加入顶级线程时,我怎么知道它是否可用于加入?当然,我可以检查它是否可连接(我使用 std::thread),但是当我这样做时,它可能会变得不可连接并且线程不是互斥锁 - 我不能只是阻止它并再次检查。所以我需要的是某种非阻塞的延迟任务池或任务查询,至少对于消息线程。同样,我可以生成等待该查询的线程并添加任务以便对其进行处理,但这真的是很好的解决方案吗?

这不一定是开箱即用的东西,我可以实现任何并发模式。

inb4: Windows、WinAPI、C++11、std::thread 用于线程。 对不起我的英语,真的找不到时间改进它。

感谢您的回答,看来我在问题描述方面做错了。确切地说,我只需要让 WNDPROC 尽快返回它的结果,因此可以从消息队列中弹出下一条消息。我需要这个,因为我记录了发送消息的时间,所以我需要快速完成它,这样它就不会影响时间测量。此外,这些消息对系统来说很紧急,我的窗口需要快速处理它们,否则会以某种方式影响性能。

再次:我需要以某种方式将确切的消息处理移动到其他线程,现在它看起来像这样:

case WM_INPUT: int timestamp = PushTimeStampToAsyncTimestampQueue(); launchLongChainOfMessageProcessing(message,timestamp); return 0;

我需要摆脱那个 launchLongChainOfMessageProcessing 并用类似的东西替换它

case WM_INPUT: int timestamp = PushTimeStampToAsyncTimestampQueue(); std::thread processThread([]() { do_work(message, timestamp);}); return 0;

【问题讨论】:

  • 您只能通过处理消息的速度慢来使您的应用程序陷入困境。请注意,消息循环和 MOST 消息几乎可以立即处理。如果您有任何需要一段时间(1 秒以上)的内容,您可以将其移至另一个线程。
  • 更新后的问题:所以您想捏造结果以提供更好的明显性能?

标签: c++ winapi design-patterns concurrency c++11


【解决方案1】:

在当前的 Windows 操作系统下,您会发现在处理大量入站消息方面,没有任何方法比使用 I/O 完成端口(简称 IOCP)的重叠 I/O 更快、更具可扩展性。它具有令人难以置信的可扩展性和极其通用的功能。

IOCP 允许您定义线程池并让这些线程由 IOCP 子系统管理和调度,等待任何基于 IO 的系统(套接字、管道、文件、任何东西)上的 IO 完成通知,如果您愿意,甚至可以不使用基于 IO 的系统;它也是一个出色的工作队列分配系统。

我提醒您不要生成线程来处理高度古怪的并发连接。您需要一个稳定的线程池,并且池足够大,这样当一个线程池由于对内核的某些调用(例如等待事件、互斥锁等)的停顿而阻塞时,另一个线程会立即分派工作。产生线程、设置和拆除上下文是昂贵的,所以避免它,幸运的是 IOCP 是一个很好的解决方案。当有工作而其他人忙于其他工作时,它能够让另一个线程从沉睡中醒来,这非常出色。

如果我设置了您所描述的系统(并且给定,您只能通过一些关于 SO 的段落来实现您的最终目标),我会毫不犹豫地使用基于 IOCP 的解决方案。

编辑在 OP 更新问题后,我奇怪地会坚持这个答案,但方式相当扭曲。他希望它尽可能快地卸载该消息队列的处理。虽然我不会为我的异步传递系统选择 Windows 消息队列,但我相信他有他的理由。

但是,我坚持使用基于 IOCP 的系统来进行实际处理。吞吐量和可扩展性简直太好了,不能用于分布式工作系统,而这似乎就是他所拥有的。没有代码,但一般算法会。

  1. 创建一个基于 IOCP 的工作组,所有线程都在 GetQueueCompletionStatus() 上等待。
  2. 收到每个 WM_INPUT 后,收集您需要的任何参数,构建您的“项目”以进行处理,并使用 PostQueuedCompletionStatus() 将项目发布到基于 IOCP 的工作组(顺便说一句,这是最方便埋葬的东西在您的工作人员“发布”功能中)。
  3. 当每个线程被唤醒时,它都会将一个工作“项”交给它们来处理。
  4. 处理完一个项目后,池线程返回到 GetQueueCompletionStatus()。

网络上有大量基于 IOCP 的示例工作队列,大多数都可以满足这种需求。除非是由恶魔编写的,否则所有内容都将比您可以在 Windows 下使用的任何其他内容具有更高的性能,这正是因为 IOCP 被紧密集成到调度程序中。

【讨论】:

  • 谢谢你的回答,我想它完全解决了描述的问题,但不幸的是它并没有解决我的问题,因为我是愚蠢的白痴并且没有正确描述它。
  • 哇。没有什么比对自己苛刻了。我会再看一下,看看我能不能找到一些东西来帮助你解决新问题(或者只是发布一个新问题,就那样)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 2011-01-16
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多