TPL Dataflow: Bounded capacity and waiting for completion

前端 未结 1 1065
北恋
北恋 2021-01-03 07:26

Below I have replicated a real life scenario as a LINQPad script for the sake of simplicity:

var total = 1 * 1000 * 1000;
var cts = new CancellationTokenSour         


        
相关标签:
1条回答
  • 2021-01-03 08:06

    Yes, this is the expected behavior, because of the BroadcastBlock:

    Provides a buffer for storing at most one element at time, overwriting each message with the next as it arrives.

    This means that if you link BroadcastBlock to blocks with BoundedCapacity, you will lose messages.

    To fix that, you could create a custom block that behaves like BroadcastBlock, but guarantees delivery to all targets. But doing that is not trivial, so you might be satisified with a simpler variant (originally from my old answer):

    public static ITargetBlock<T> CreateGuaranteedBroadcastBlock<T>(
        IEnumerable<ITargetBlock<T>> targets, DataflowBlockOptions options)
    {
        var targetsList = targets.ToList();
    
        var block = new ActionBlock<T>(
            async item =>
            {
                foreach (var target in targetsList)
                {
                    await target.SendAsync(item);
                }
            }, new ExecutionDataflowBlockOptions
            {
                BoundedCapacity = options.BoundedCapacity,
                CancellationToken = options.CancellationToken
            });
    
        block.Completion.ContinueWith(task =>
        {
            foreach (var target in targetsList)
            {
                if (task.Exception != null)
                    target.Fault(task.Exception);
                else
                    target.Complete();
            }
        });
    
        return block;
    }
    

    Usage in your case would be:

    var bcBlock = CreateGuaranteedBroadcastBlock(
        new[] { bufferBlock1, bufferBlock2 }, dbOptions);
    
    0 讨论(0)
提交回复
热议问题