数据流基础——关联的块
TPL数据流是一个强大的库,通过它可以创建网格或管道,然后异步发送数据。数据流的代码具有非常明显的声明式风格:一般来说,首先要完整定义网格,然后开始处理数据,最终网格成为一种供数据流井的结构。
每个网格均由若干个彼此关联的块组成,独立的块很简单,并且只负责数据中的单个步骤,当块完成了对数据的处理时,他会将结果传递给所有与之关联的块。
若想使用TPL数据流,需要在应用程序中安装System.Threading.Tasks.Dataflow这个NuGet包。
问题
假设要把数据流块彼此关联起来,从而创建一个网格
解决方案
由TPL数据流提供的块只定义了最基本的方法,许多实用的TPL数据流方法其实是扩展方法。LinkTo扩展方法为关联数据流提供了一种简单方式
var multiplyBlock=new TransformBlock<int,int>(item=>item*2);
var subtractBlock=new TransformBlock<int,int>(item=>item-2);
//关联之后,从multiplyBlock离开的值,会进入subtractBlock
multiplyBlock.LinkTo(subtractBlock);
在默认情况下,关联的数据块只传播数据,他们并不会传播完成状态(或者错误)。在面对管道等线性得到数据流时,可能需要传播完成状态,若要传播完成状态(或错误),可以设置连接中的PropagateCompletion选项
var multiplyBlock=new TransformBlock<int,int>(item=>item*2);
var subtractBlock=new TransformBlock<int,int>(item=>item-2);
var options=new DataflowLinkOptions{PrograteCompletion=true};
//关联之后,从multiplyBlock离开的值,会进入subtractBlock
multiplyBlock.LinkTo(subtractBlock);
//第一个数据流块的完成状态会自动传播到第二个数据流块
multBlock.Complete();
await subtractBlock.Completion;
讨论
一旦关联起来,数据就会自动地从源块流至目标块。PropagateCompletion选项会将数据联通完成状态一起传播出去。如果传播完成状态管道很长,那么原始错误可能被嵌套在多个AggregateException实例中。Flatten能在这种情况下协助处理错误。
关联数据流块的方式多种多样。网格可以包含分叉、连接,甚至循环。但是,简单的先行管道足以应付大多数场景。