Search code examples
c#tpl-dataflow

Completion is not being propagated between dataflow blocks


I am studying Dataflow basics. Here is a code sample which looks correct to me but does not work. Instead of returning result integer value it freezes. In my understanding it is because completing is not being propagated between blocks.

    public static int Process(int value)
    {
        var multiplyBlock = new TransformBlock<int, int>(item => item * 2);
        var subtractBlock = new TransformBlock<int, int>(item => item - 2);

        var options = new DataflowLinkOptions() { PropagateCompletion = true };
        multiplyBlock.LinkTo(subtractBlock, options);

        multiplyBlock.Post(value);

        multiplyBlock.Complete();
        subtractBlock.Completion.Wait(); // <--- code freezes here

        return subtractBlock.Receive();
    }

Could you please help me understand what is missing?


Solution

  • The subtractBlock.Complete() is called automatically when the upstream multiplyBlock.Completion is completed (because of the PropagateCompletion = true ). At that point the subtractBlock.Completion will not complete immediately. It will complete when both the following two conditions become true:

    1. All the items in the input buffer of the subtractBlock have been processed.
    2. All the items in the output buffer of the subtractBlock have been accepted by a block downstream.

    In other words both the input and output buffers of a TransformBlock<TInput, TOutput> must be empty, otherwise the block will never complete. In your case the output buffer of the block is not emptied, because the block is not linked to anything. You can solve this problem either by linking it to the NullTarget, or by replacing it with an ActionBlock<TInput>.

    Btw be aware that currently the TPL Dataflow library has a bug that could cause a pipeline to never complete, under very specific and rare conditions. You can find demonstrations of this bug here. This bug has existed forever, and is unlikely to be resolved any time soon.