TPL Complete vs Completion

后端 未结 1 766
南旧
南旧 2020-12-10 19:10

I need to import customer related data from legacy DB and perform several transformations during the process. This means a single entry needs to perform additional \"events\

相关标签:
1条回答
  • 2020-12-10 19:50

    You're almost there, you need to call Complete on the first block in the pipeline then await Completion on the last block. Then in your links you need to propagate completion like this:

    private async static void Main(string[] args) {
        var transformBlock = new TransformBlock<int, MyClass1>(delegate (int id)
        {
            Console.WriteLine($"TransformBlock(id: {id})");
            return new MyClass1(id, "Star Wars");
        });
        var transformManyBlock = new TransformManyBlock<MyClass1, MyClass2>(delegate (MyClass1 myClass1)
        {
            Console.WriteLine($"TransformManyBlock(myClass1: {myClass1.Id}|{myClass1.Value})");
            Thread.Sleep(1000);
            return GetMyClass22Values(myClass1);
        });
    
        var actionBlock = new ActionBlock<MyClass2>(delegate (MyClass2 myClass2)
        {
            Console.WriteLine($"ActionBlock(myClass2: {myClass2.Id}|{myClass2.Value})");
            Thread.Sleep(1000);
        });
    
        //propagate completion
        transformBlock.LinkTo(transformManyBlock, new DataflowLinkOptions() { PropagateCompletion = true });
        transformManyBlock.LinkTo(actionBlock, new DataflowLinkOptions() { PropagateCompletion = true});
        foreach(var id in ids) {
            transformBlock.Post(id);
        }
    
    
        //Complete the first block
        transformBlock.Complete();
    
        //wait for completion to flow to the last block
        await actionBlock.Completion;
    } 
    

    You can also incorporate the batch block into your pipeline and remove the need for the TryRecieve call but that seems like another part of your flow.

    Edit

    Example of propagating completion to multiple blocks:

    public async static void Main(string[] args) {
    
        var sourceBlock = new BufferBlock<int>();
    
        var processBlock1 = new ActionBlock<int>(i => Console.WriteLine($"Block1 {i}"));
    
        var processBlock2 = new ActionBlock<int>(i => Console.WriteLine($"Block2 {i}"));
    
        sourceBlock.LinkTo(processBlock1);
        sourceBlock.LinkTo(processBlock2);
    
        var sourceBlockCompletion = sourceBlock.Completion.ContinueWith(tsk => {
            if(!tsk.IsFaulted) {
                processBlock1.Complete();
                processBlock2.Complete();
            } else {
                ((IDataflowBlock)processBlock1).Fault(tsk.Exception);
                ((IDataflowBlock)processBlock2).Fault(tsk.Exception);
            }
        });
    
        //Send some data...
    
        sourceBlock.Complete();
        await Task.WhenAll(sourceBlockCompletion, processBlock1.Completion, processBlock2.Completion);
    }
    
    0 讨论(0)
提交回复
热议问题