BufferBlock and ActionBlock with BoundedCapacity do not use maximum DOP

I have this code:

var data = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); var action = new ActionBlock<int>(async id => { Console.WriteLine("[{0:T}] #{1}: Start", DateTime.Now, id); await Task.Delay(1000); Console.WriteLine("[{0:T}] #{1}: End", DateTime.Now, id); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1, MaxDegreeOfParallelism = -1 }); data.LinkTo(action, new DataflowLinkOptions { PropagateCompletion = true }); for (var id = 1; id <= 3; id++) { Console.WriteLine("[{0:T}] Sending {1}", DateTime.Now, id); data.SendAsync(id).Wait(); Console.WriteLine("[{0:T}] Sending {1} complete", DateTime.Now, id); } data.Complete(); Task.WhenAll(data.Completion, action.Completion).Wait(); 

And this code gets me this output:

 [22:31:22] Sending 1 [22:31:22] Sending 1 complete [22:31:22] Sending 2 [22:31:22] #1: Start [22:31:22] Sending 2 complete [22:31:22] Sending 3 [22:31:23] #1: End [22:31:23] #2: Start [22:31:23] Sending 3 complete [22:31:24] #2: End [22:31:24] #3: Start [22:31:25] #3: End 

Why ActionBlock n't ActionBlock work in parallel, although it has unlimited DOP?

+5
source share
1 answer

The reason your ActionBlock has a limited degree of parallelism is because it has BoundedCapacity of 1. BoundedCapacity (as opposed to InputCount ) enables the item to be processed at the moment. This can be easily demonstrated:

 var block = new ActionBlock<int>(_ => Task.Delay(-1), new ExecutionDataflowBlockOptions { BoundedCapacity = 1, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); await block.SendAsync(4); // Adds a new item await block.SendAsync(4); // Blocks forever 

This means that when you set MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded , the block cannot accept more than one element at a time and therefore practically limits the degree of parallelism.

You can fix this by setting a larger BoundedCapacity :

 var action = new ActionBlock<int>(async id => { Console.WriteLine("[{0:T}] #{1}: Start", DateTime.Now, id); await Task.Delay(1000); Console.WriteLine("[{0:T}] #{1}: End", DateTime.Now, id); }, new ExecutionDataflowBlockOptions { BoundedCapacity = 10, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); 
+7
source

Source: https://habr.com/ru/post/977295/


All Articles