I'm looking for a way to await
all items to be processed via TPL TransformBlock
.
Sample code:
var transformBlock = new TransformBlock<int, int>(async number =>
{
await Task.Delay(TimeSpan.FromMilliseconds(300));
return number * 2;
}, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
});
foreach (var number in Enumerable.Range(1, 100))
{
transformBlock.Post(number);
}
transformBlock.Complete();
At this point I have a call to Complete, which to my understanding signals to TransformBlock
to not receive any more items & to finish processing all available data (available in InputQueue
).
But I'm not sure how to await
for all items to be available ?
Awaiting Completion task is not a solution becase as the answer states:
An instance of TransformBlock is not considered "complete" until the following conditions are met:
- TransformBlock.Complete() has been called
- InputCount == 0 – the block has applied its transformation to every incoming element
- OutputCount == 0 – all transformed elements have left the output buffer
One way I found is to await
all tasks returned from ReceiveAsync
, e.g.
var tasks = new List<Task<int>>();
foreach (var number in Enumerable.Range(1, 100))
{
transformBlock.Post(number);
tasks.Add(transformBlock.ReceiveAsync());
}
transformBlock.Complete();
await Task.WhenAll(tasks);
tasks.Select(t => t.GetAwaiter().GetResult())
.ToList()
.ForEach(Console.WriteLine);
However, I'm not really sure this is 100 % correct.
Another options I see in this answer suggestion made to add another TPL blocks and propogate completion, that way we can await transform block's completion and then consume results from linked TPL block, but it does seem like overcomplication of the task & I'm assuming there is better (built-in or less verbose) way ?