TPL 数据流未完成多个目标

TPL Dataflow not completing with multiple targets

我有一个 BufferBlock 链接到两个目标块。数据流未完成。我已遵循 的建议,但无法正确完成传播。

如有任何帮助,我们将不胜感激。

// define blocks
var bufferBlock = new BufferBlock<int>(); 

var actionBlock1 = new TransformBlock<int, int>(i =>
{
    Console.WriteLine($"actionBlock1: {i}");
    return i;
});
var actionBlock2 = new ActionBlock<int>(i =>
{
    Console.WriteLine($"actionBlock2: {i}");
});

// link blocks 
bufferBlock.LinkTo(actionBlock1, i => i == 1);
bufferBlock.LinkTo(actionBlock2, i => i == 2);
bufferBlock.LinkTo(DataflowBlock.NullTarget<int>()); 

// push to block 
var items = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (var i in items)
{
    bufferBlock.Post(i);
}

// wait for all operations to complete
bufferBlock.Complete();

// NB: block will only propagate completion to one block regardless of how many blocks are linked. This even applies to the BroadcastBlock that broadcasts messages, it will not broadcast completion. In that case you can configure a continuation on the Completion Task
// see 
var bufferBlockCompletion = bufferBlock.Completion.ContinueWith(tsk =>
{
    if (!tsk.IsFaulted)
    {
        actionBlock1.Complete();
        actionBlock2.Complete();
    }
    else
    {
        ((IDataflowBlock)actionBlock1).Fault(tsk.Exception);
        ((IDataflowBlock)actionBlock2).Fault(tsk.Exception);
    }
});

await Task.WhenAll(bufferBlockCompletion, actionBlock1.Completion, actionBlock2.Completion);

actonBlock1 是一个 TransformBlock,没有链接到任何东西。该块产生的任何项目都将保留在其输出缓冲区中,在这个 cas 中只有数字 1。如果项目卡在输出中,该块将永远无法完成。您可以根据您的具体需要,通过几种不同的方式解决这个问题。

1) 将 TransformBlock 更改为 ActionBlock

2) Link TransformBlockNullTarget 或另一个块。