【发布时间】:2018-03-26 10:52:52
【问题描述】:
我是 TPL Dataflow ActionBlock、TransformBlock 等的新手。我曾经练习 Task.ContinueWith() 在需要时创建管道。我最近开始练习 TPL 数据流及其块。
但是我对这两者之间的确切区别有点困惑。那你能告诉我什么时候用什么吗?
【问题讨论】:
标签: c# task-parallel-library .net-4.5 tpl-dataflow
我是 TPL Dataflow ActionBlock、TransformBlock 等的新手。我曾经练习 Task.ContinueWith() 在需要时创建管道。我最近开始练习 TPL 数据流及其块。
但是我对这两者之间的确切区别有点困惑。那你能告诉我什么时候用什么吗?
【问题讨论】:
标签: c# task-parallel-library .net-4.5 tpl-dataflow
这是两种不同的方法,它们具有相似的行为,但实际上并不相互关联。 ContinueWith 为 Task 安排延续。使用async/await,您实际上不需要使用ContinueWith,因为async/await 关键字已经将您的方法的其余部分安排为延续。例如AsyncAwait 和Continuation 这两种方法产生相同的结果。
public async Task AsyncAwait()
{
await DoAsync();
DoSomethingElse();
}
public async Task Continuation()
{
await DoAsync().ContinueWith(_ => DoSomethingElse());
}
public Task DoAsync() => Task.Delay(TimeSpan.FromSeconds(1));
public void DoSomethingElse()
{
//More Work
}
另一方面,LinkTo 在两个Tpl-Dataflow 块之间创建一个一次性链接。该链接可以通过多种方式配置see DatflowLinkOptions。最多的配置项之一是PropagateCompletion。正如您所希望看到的,数据流链接不仅仅是简单的延续。您可以传递完成,添加谓词以过滤数据,甚至将块链接到复杂的结构中,例如网格或反馈循环。此外,数据流链接允许您设置“背压”来限制流量。如果下游块过载并且其输入缓冲区已填满,则上游块可以暂停处理。数据流链接的完整行为并不容易通过手动延续来实现。
public ITargetBlock<int> BuildPipeline()
{
var block1 = new TransformBlock<int, int>(x => x);
var block2 = new ActionBlock<int>(x => Console.WriteLine(x));
block1.LinkTo(block2 , new DataflowLinkOptions() { PropagateCompletion = true });
return block1;
}
除非您正在执行复杂的链接,否则您应该始终更喜欢使用async/await 而不是原始延续。 async/await 使代码更易于编写、理解和维护。 LinkTo 仅适用于数据流块,应被视为与延续分开的东西,用于构建数据流网络。
【讨论】: