好的,所以解决方案的架构将取决于一件事:每个队列项目的处理时间是否根据项目的数据而变化?
如果没有,那么您可以在处理线程之间进行循环。这将相当容易实现。
如果处理时间确实有所不同,那么您将需要具有更多“下一个可用”感觉的东西,这样无论哪个线程恰好是空闲的,都会首先获得处理数据项的工作。
解决了这个问题后,您将通常围绕如何在队列读取器和处理线程之间进行同步。“下一个可用”和“循环”之间的区别在于您如何进行同步。
我对 C# 并不太熟悉,但我听说过一种叫做后台工作者的野兽。这可能是实现这一目标的一种可接受的方式。
对于循环,只需为每个队列项启动一个后台工作程序,将工作人员的引用存储在一个数组中。例如,将自己限制在 16 个正在进行的后台工作人员。这个想法是,在开始 16 之后,您将在开始 17 之前等待第一个完成,依此类推。我相信后台工作人员实际上作为线程池上的作业运行,因此这将自动将任何时候实际运行的线程数限制为适合底层硬件的数量。要等待后台工作人员,请参阅this。等待后台工作人员完成后,您将处理其结果并启动另一个。
对于下一个可用的方法,它并没有太大的不同。而不是等待第一个完成,您将使用 WaitAny() 等待任何工作人员完成。您处理任何一个完成的返回,然后启动另一个并返回到 WaitAny()。
这两种方法的一般理念是始终保持多个线程处于沸腾状态。下一个可用方法的一个特点是您发出结果的顺序不一定与输入项的顺序相同。如果这很重要,那么使用比 CPU 内核更多的后台工作程序的循环方法将相当有效(线程池将刚刚开始调试但还没有运行工作程序)。然而,延迟会随着处理时间而变化。
BTW 16 是根据您认为运行该软件的 PC 上的内核数量选择的任意数字。更多的核心,更大的数量。
当然,在看似不安和不断变化的 .NET 世界中,现在可能有更好的方法来做到这一点。
祝你好运!