Search code examples
c#.nettask-parallel-librarytpl-dataflow

How do I detect all TransformManyBlocks have completed


I have a TransformManyBlock that creates many "actors". They flow through several TransformBlocks of processing. Once all of the actors have completed all of the steps I need to process everything as a whole again.

The final

var CopyFiles = new TransformBlock<Actor, Actor>(async actor =>
{
    //Copy all fo the files and then wait until they are all done
    await actor.CopyFiles();
    //pass me along to the next process
    return actor;
}, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = -1 });

How do I detect when all of the Actors have been processed? Completions seems to be propagated immediately and only tell you there are no more items to process. That doesn't tell me when the last Actor is finished processing.


Solution

  • Completion in TPL Dataflow is done by calling Complete which returns immediately and signals completion. That makes the block refuse further messages but it continues processing the items it already contain.

    When a block completes processing all its items it completes its Completion task. You can await that task to be notified when all the block's work has been done.

    When you link blocks together (with PropogateCompletion turned on) you only need to call Complete on the first and await the last one's Completion property:

    var copyFilesBlock = new TransformBlock<Actor, Actor>(async actor =>
    {
        await actor.CopyFilesAsync();
        return actor;
    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 });
    
    // Fill copyFilesBlock
    
    copyFilesBlock.Complete();
    await copyFilesBlock.Completion;