Reputation: 125
I have a BufferBlock linked to two Target Blocks. The dataflow does not complete. I have followed the suggestions from this post, but I can't get the completion propagation right.
Any help would be appreciated.
// 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 https://stackoverflow.com/questions/47310402/tpl-complete-vs-completion/47311537#47311537
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);
Upvotes: 1
Views: 470
Reputation: 7091
actonBlock1
is a TransformBlock
that is not linked to anything. Any items that the block produces will remain in its output buffer, in this cas only the number 1. With items stuck in the output the block can never complete. You can fix that a couple of different ways depending on what exactly you need.
1) Change the TransformBlock
to an ActionBlock
2) Link the TransformBlock
to a NullTarget
or another block.
Upvotes: 3