在.Net中实现并行任务队列

时间:2013-01-08 10:30:08

标签: c# .net multithreading task-parallel-library

图像说的不仅仅是文字,所以这基本上是我想要达到的目的:
(为了简洁起见,我也使用了水果类比) enter image description here

我过去很多次使用.Net类的不同之王(BackGroundWOrkers,ThreadPool,Self Made Stuff ......)完成了这种事情。

我在这里要求提供建议,并就如何有效地做到这一点获得新的想法 这是一个高计算程序,因此我收到数百万(结构相似但内容不相似)的数据,这些数据必须排队才能根据其内容类型进行处理。因此,我想避免为每个要处理的单个数据创建并行任务(这会使CPU过载并且设计不佳恕我直言)。这就是为什么我想到只有一个线程运行EACH数据TYPE,专门处理它(知道“Press Juice”方法是通用的,独立于要按下的水果)

欢迎任何想法和实施建议。
我可以自由地提供任何进一步的细节。

3 个答案:

答案 0 :(得分:19)

TPL DataFlow似乎是一个非常强大的候选人。

Take a read of the intro here.

答案 1 :(得分:9)

如果您真正想要的是每种类型的水果的一个线程(或一个恒定数量的线程),那么最简单的解决方案可能是对每种类型的水果使用BlockingCollection。您的数据总线将为这些集合提供水果,您的处理线程将从中获取。但这意味着如果现在没有苹果,线程将被阻止,什么都不做。

更灵活,更有效的方法是使用TPL Dataflow。有了这个,你不使用线程或任务,你使用块。例如,您的Thread C可以表示为TransformBlock<Apple, AppleJuice>

默认情况下,每个块最多使用一个线程,但可以轻松配置它们以使用更多线程(通过设置MaxDegreeOfParallelism)。此外,数据流块可以很好地适应新的C#5.0 async - await,这可能是一个很大的优势。

还有一些你应该小心的事情。例如,默认情况下,TDF针对吞吐量而非延迟进行了优化。因此,如果你的线程池很忙并且你有很多橙子进来而且只有一个苹果,那么苹果可能只在所有橙子被处理后才会被处理掉。但这也可以通过正确配置块来解决(通过设置MaxMessagesPerTask)。

答案 2 :(得分:1)

我会警告“每种数据类型的工作线程”方法。这假设实际输入负载将符合开发人员方便的等价类。你知道香蕉比橘子慢5倍吗?如果每个星期二都是“苹果庆祝日”,每个人都会吃比平时多的水果,那么会发生什么呢?所有这些都是苹果?

并行运行是关于性能,而不是关于域。不要在域之后对其进行建模,对其进行建模以提供最低的平均周期时间。