I would build such a block from BufferBlock<T> : the method accepts a delegate that represents the ITargetBlock<T> side of the block and returns the ISourceBlock<T> side. Thus, a delegate can send input to a block, but from the outside it looks like a block that only produces output.
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; }
Usage example:
var producer = CreateProducerBlock<int>(async target => { await target.SendAsync(10); await target.SendAsync(20); }); ITargetBlock<int> consumer = β¦; producer.LinkTo(consumer);
svick source share