Search code examples
c#tpl-dataflow

Why is TPL Post response different in Bounded BroadcastBlock and BufferBlock?


I expected that result1 in the last assertion equal false on BroadcastBlock as on BufferedBlock, but it is not the case.

I'm using latest System.Threading.Tasks.Dataflow version 8.0.1

            var block2 = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 2 });
            var result2 = block2.Post(1);
            result2 = block2.Post(1);
            
            Debug.Assert(result2 == true);
            
            result2 = block2.Post(1);
            Debug.Assert(result2 == false);   // this is expected and work

            var block1 = new BroadcastBlock<int>(i => i, new DataflowBlockOptions { BoundedCapacity = 2});
            var result1 = block1.Post(1);
            
            result1 = block1.Post(1);
            Debug.Assert(result1 == true);

            result1 = block1.Post(1);
            Debug.Assert(result1 == false);   // this fails

Is that a bug or expected?


Solution

  • Reading the source, it looks like the BroadcastBlock adds the new message to an internal queue, then asynchronously tries to forward it to all consumers. Once that's done, it removes it from its internal queue.

    If you've set a capacity on the internal queue (with BoundedCapacity), and that queue has filled up (so you've added items faster than it's been able to offer them to all consumers), then Post will return false.

    In your test, because the task of forwarding the item happens asynchronously on a background thread, there's a race between how quickly you can add items, vs how quickly it can offer them to all consumers. On DotNetFiddle, your final Post returns false, however if I add a sleep before the final Post (to give the background thread a chance to clear the internal queue), the final Post returns true.