[英]Understanding TPL Dataflow, Blocks, and Continuation Tasks
我正在一个需要满足TPL Dataflow理想情况的项目中工作。 由于对它的经验相对有限(并且我之前做过的事情),我一直在阅读Microsoft的文档以及可以在网上找到的文章来进行梳理。
完成此操作后,我构建了将一系列块链接在一起的代码(主要是TransformBlock
并以一个ActionBlock
结尾,如下所示:
var block1 = new TransformBlock<T, U>(async input => {});
var block2 = new TransformBlock<U, V>(async input => {});
var block3 = new ActionBlock<V>(async input => {});
block1.LinkTo(block2);
block2.LinkTo(block3);
foreach(var item in items)
{
await block1.SendAsync(item);
}
block1.Complete();
await block3.Completion;
文章中的某人(我找不到)建议管道中应该有继续任务,以将块标记为已完成。 这是他们为此提供的代码。
// Create the continuation tasks in the pipeline that marks each block as complete.
await block1.Completion.ContinueWith(t =>
{
if (t.IsFaulted) { ((IDataflowBlock)block2).Fault(t.Exception); }
else { block2.Complete(); }
});
await block2.Completion.ContinueWith(t =>
{
if (t.IsFaulted) { ((IDataflowBlock)block3).Fault(t.Exception); }
else { block3.Complete(); }
});
我承认我不完全了解此代码的功能以及是否需要它。 当我尝试在我刚刚编写的代码中运行此代码时,该代码将挂在第一个ContinueWith
,并且永远不会使其运行管道。
我希望能得到更多的解释,因为我想更好地了解这里发生的细微差别。
对于线性管道,您所需要做的就是PropagateCompletion
。 该选项会传播“ Completion
”以及“ Faults
,然后将其异常附加到最终“ Completion Task
:
var linkOptions = new DataflowLinkOptions() { PropagateCompletion = true };
block1.LinkTo(block2, linkOptions);
block2.LinkTo(block3, linkOptions);
继续是不必要的。 但是,如果您有分配给多个块的管道,则需要自己处理完成和错误传播,如下所示 。
该代码挂在第一个
ContinueWith
发生这种情况是因为您await
继续,所以如果您在调用Complete()
之前这样做,那么block1
将永远不会完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.