Consider the following pipeline:
public static void Main()
{
var firstBlock = new TransformBlock<string, string>(s =>
{
Console.WriteLine("FirstBlock");
return s + "-FirstBlock";
});
var batchBlock = new BatchBlock<string>(100, new GroupingDataflowBlockOptions { Greedy = true });
var afterBatchBlock = new TransformManyBlock<string[], string>(strings =>
{
Console.WriteLine("AfterBatchBlock");
return new[] { strings[0] + "-AfterBatchBlock" };
});
var lastBlock = new ActionBlock<string>(s =>
{
Console.WriteLine($"LastBlock {s}");
});
firstBlock.LinkTo(batchBlock, new DataflowLinkOptions { PropagateCompletion = true }, x => x.Contains("0"));
batchBlock.LinkTo(afterBatchBlock, new DataflowLinkOptions { PropagateCompletion = true });
afterBatchBlock.LinkTo(lastBlock, new DataflowLinkOptions { PropagateCompletion = true });
firstBlock.LinkTo(lastBlock, new DataflowLinkOptions { PropagateCompletion = true });
firstBlock.Post("0");
firstBlock.Complete();
firstBlock.Completion.GetAwaiter().GetResult();
batchBlock.Completion.GetAwaiter().GetResult();
afterBatchBlock.Completion.GetAwaiter().GetResult();
lastBlock.Completion.GetAwaiter().GetResult();
}
Running this code gets blocked with the following output:
FirstBlock
AfterBatchBlock
What I think is happening behind the scenes is the following:
- FirstBlock sends a Completion signal to all its linked targets (BatchBlock, AfterBatchBlock, LastBlock)
- BatchBlock and LastBlock gets completed
- AfterBatchBlock then tries to pass its output to LastBlock but it is already completed and it gets stuck forever.
My question is:
- Is it a bug?
- Assuming it is by design, what is the recommended way to overcome the bad state my pipeline reached