我使用TPL Dataflow
构建了两个管道:
TransformBlock => TransformBlock => BatchBlock => ....
TransformBlock => BatchBlock => TransformBlock => ....
我想完成
/ => Transform Block => TransformBlock => BatchBlock => ....
BatchBlock /
\
\ => Transform Block => BatchBlock => TransformBlock => ....
但是只有第一个管道被执行。
我的代码
batchMediaBlock.LinkTo(pipelineA.FirstBlock, new DataflowLinkOptions {PropagateCompletion = true});
batchMediaBlock.LinkTo(pipelineB.FirstBlock, new DataflowLinkOptions {PropagateCompletion = true});
我该如何做到这一点?
答案 0 :(得分:1)
您BroadcastBlock
之后需要BatchBlock
。但请注意,完成只会传播到您的TransformBlock
之一。请参阅下面的处理完成的部分示例:
using System.Threading.Tasks.Dataflow;
namespace MyDataflow {
class MyDataflow {
public void HandlingCompletion() {
var batchBlock = new BatchBlock<int>(10);
var broadcastBlock = new BroadcastBlock<int[]>(_ => _);
var xForm1 = new TransformBlock<int[], int[]>(_ => _);
var xForm2 = new TransformBlock<int[], int[]>(_ => _);
batchBlock.LinkTo(broadcastBlock, new DataflowLinkOptions() { PropagateCompletion = true });
broadcastBlock.LinkTo(xForm1);
broadcastBlock.LinkTo(xForm1);
broadcastBlock.Completion.ContinueWith(broadcastBlockCompletionTask => {
if (!broadcastBlockCompletionTask.IsFaulted) {
xForm1.Complete();
xForm2.Complete();
}else {
((IDataflowBlock)xForm1).Fault(broadcastBlockCompletionTask.Exception);
((IDataflowBlock)xForm2).Fault(broadcastBlockCompletionTask.Exception);
}
});
xForm1.Completion.ContinueWith(async _ => {
try {
await xForm2.Completion;
//continue passing completion / fault on to rest of pipeline
} catch {
}
});
}
}
}
或者,如果您的管道再次收敛,则可以在继续BroacastBlock
后为每个管道分别处理完成。提供的示例将同时完成管道中的每个步骤,同步流动完成。
答案 1 :(得分:1)
默认情况下,TPL数据流中的链接被认为是贪婪的,因此第一个目标始终会收到消息并且将其从上一个块中删除&#39;输出,这就是你的第二个块没有得到任何消息的原因。这种情况可以通过BroadcastBlock<T>
解决,
确保当前元素在允许元素被覆盖之前广播到任何链接目标。
您还应该注意,此阻止执行克隆消息。
所以你基本上应该在批量阻止后添加广播,但是!你不应该把你的完成从广播块传播给消费者 - 只有第一个才能完成。您应该为@JSteward建议为您的广播添加ContinueWith
处理程序。