TPL DataFlow与BlockingCollection

时间:2014-01-16 13:44:06

标签: .net task-parallel-library data-synchronization tpl-dataflow

我知道BlockingCollection最适合消费者/生产者模式。但是,何时使用TPL DataFlow库中的ActionBlock

我最初的理解是针对IO操作,保留BlockingCollection,同时CPU密集型操作适合于ActionBlock。但我觉得这不是整个故事...还有其他见解吗?

2 个答案:

答案 0 :(得分:8)

TPL Dataflow更适合基于演员的设计。这意味着如果你想链接生产者和消费者,TDF会更容易。

TPL数据流的另一大优点是它在构建时考虑了async。您可以以async方式(同时)同步生成和使用,这非常有用。 (我主要以同步方式生成并以非阻塞async方式使用)。

您还可以非常轻松地设置有界容量和并行度。

TL; DR:BlockingCollection是一个简单而通用的工具。 TPL Dataflow更加强大,但对于特定问题可能过度或不合适。

答案 1 :(得分:3)

不确定重复使用单词Block是否会导致混淆。它们是非常不同的东西。

你是对的,BlockingCollection非常适合生产者消费者的情况,因为在数据可用之前它会阻止尝试从中读取。但是,BlockingCollection不是TPL Dataflow的一部分。它在.NET 4.0中被引入作为新的线程安全集合类型之一。

然而,ActionBlock是由TPL Dataflow定义的一种“块”,可用于执行操作。从这个意义上讲,阻止更多是指它作为数据流的一部分使用。

TPL数据流中定义的数据流由块组成,有三种主要类型。来自文档:

  

TPL数据流库由数据流块组成,数据流块是缓冲和处理数据的数据结构。 TPL定义了三种数据流块:源块,目标块和传播块。源块充当数据源并且可以从中读取。目标块充当数据接收器并可以写入。传播器块充当源块和目标块,并且可以被读取和写入。 TPL定义了System.Threading.Tasks.Dataflow.ISourceBlock接口来表示源,System.Threading.Tasks.Dataflow.ITargetBlock来表示目标,System.Threading.Tasks.Dataflow.IPropagatorBlock来表示传播者。 IPropagatorBlock继承自ISourceBlock和TargetBlock。   TPL数据流库提供了几种预定义的数据流块类型,这些类型实现了ISourceBlock,ITargetBlock和IPropagatorBlock接口。本文档的“预定义数据流块类型”一节中介绍了这些数据流块类型。

ActionBlock是一种ITargetBlock,它接受输入,执行操作,然后停止。

要回答您的第一个问题,我认为您的过程很简单时可以使用BlockingCollection。当你的过程更复杂时,你会使用TPL Dataflow,在这种情况下,你可能不需要BlockingCollection。

这里有使用BlockingCollection的Producer-Consumer问题的示例: http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx?Redirected=true 和这里: http://programmerfindings.blogspot.co.uk/2012/07/producer-consumer-problem-using-tpl-and.html

这些都不使用Dataflow。这里有一个使用Dataflow的例子:

http://msdn.microsoft.com/en-us/library/hh228601(v=vs.110).aspx

另外,我强烈建议您在此处阅读TPL Dataflow文档:

http://msdn.microsoft.com/en-us/library/hh228601(v=vs.110).aspx

如果你正在实施任何复杂的事情。