Search code examples
c#multithreadingasynchronoustask-parallel-librarytpl-dataflow

Is there a TPL dataflow block that doesn't take input but returns output?


The title of my question says it all.

I am looking for a TPL dataflow block that doesn't need an input.

Right now I am using a transform block but it's input is unused.


Solution

  • I would build a block like this from a BufferBlock<T>: the method accepts a delegate that presents the ITargetBlock<T> side of the block and returns the ISourceBlock<T> side of it. This way, the delegate can send input to the block, but from the outside, it looks like a block that only produces output.

    The code:

    public static ISourceBlock<T> CreateProducerBlock<T>(
        Func<ITargetBlock<T>, Task> producer,
        int boundedCapacity = DataflowBlockOptions.Unbounded)
    {
        var block = new BufferBlock<T>(
            new ExecutionDataflowBlockOptions { BoundedCapacity = boundedCapacity });
    
        Task.Run(async () =>
        {
            try
            {
                await producer(block);
    
                block.Complete();
            }
            catch (Exception ex)
            {
                ((IDataflowBlock)block).Fault(ex);
            }
        });
    
        return block;
    }
    

    Example usage:

    var producer = CreateProducerBlock<int>(async target =>
    {
        await target.SendAsync(10);
        await target.SendAsync(20);
    });
    
    ITargetBlock<int> consumer = …;
    
    producer.LinkTo(consumer);