0

I'm looking for a collection like BufferBlock

but with methods like:

SendAsync<T>(T[])
T[] ReceiveAsync<T>()

Is anyone can help with?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
gabba
  • 2,815
  • 2
  • 27
  • 48
  • Did you check the extension methods? – Hackerman Sep 13 '18 at 13:05
  • @Hackerman, yep... doublechecked ;) can you point me if I'm missing something? – gabba Sep 13 '18 at 13:06
  • Why don't you use BufferBlock? BTW it does have such methods. Check [How to: Implement a Producer-Consumer Dataflow Pattern](https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-implement-a-producer-consumer-dataflow-pattern) – Panagiotis Kanavos Sep 13 '18 at 15:16
  • As for something *other* than Bufferblock that supports pub/sub explicitly, you can try the new System.Threading.Tasks.Channels package – Panagiotis Kanavos Sep 13 '18 at 15:17
  • [ReceiveAsync](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.dataflow.dataflowblock.receiveasync?view=netcore-2.1) and [SendAsync](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.dataflow.dataflowblock.sendasync?view=netcore-2.1) are available as extension methods. Perhaps you need to cast the BufferBlock to the appropriate interface first? – Panagiotis Kanavos Sep 13 '18 at 15:21
  • @PanagiotisKanavos `ReceiveAsync` and `SendAsync` do not handle arrays. – JSteward Sep 13 '18 at 17:16
  • @JSteward, yes exactly: the question about collection able to send and receive batches – gabba Sep 13 '18 at 20:42
  • 1
    Added another option, the `BatchBlock` might work better for you but it depends on your use case. – JSteward Sep 13 '18 at 20:48

2 Answers2

1

These methods aren't available, SendAsync<T> only takes a single T and RecieveAsync<T> only returns a single T, not arrays.

SendAsync<T>(T[])
T[] ReceiveAsync<T>()

However there is TryReceiveAll<T>(out IList<T> items) and you can call SendAsync<T> in a loop to send an array into the BufferBlock or write your own extension method, something like this:

public static async Task SendAllAsync<T>(this ITargetBlock<T> block, IEnumerable<T> items)
{
    foreach(var item in items)
    {
         await block.SendAsync(item)
    }
}

Note that SendAsync does return a bool indicating acceptance of the messages, you could return an array of booleans or just return if any of them come back false but that's up to you.

Likely it would be easier to use a BatchBlock<T> that you can send items to as singles using a loop but emits the items in batches, which would be easier than using TryRecieveAll if you're building a pipeline. BatchBlock Walkthrough and BatchBlock Example

JSteward
  • 6,833
  • 2
  • 21
  • 30
  • Thanks for the BatchBlock, it's close to what I was looking for. Ideally if collection can handle batch input asynchronously and can a read asynchronously a batch with just a max size without outside timer – gabba Sep 13 '18 at 21:13
0

ReceiveAsync and SendAsync are available as extension methods on the ISourceBlock and ITargetBlockT<> interfaces. This means that you have to cast the block to those interfaces in order to use the extension methods, eg :

var buffer=new BufferBlock<string>();

var source=(ISourceBlock<string>)buffer;
var target=(ITargetBlock<string>)buffer;

await target.SendAsync("something");

Typically that's not a problem because all Dataflow methods accept interfaces, not concrete types, eg :

async Task MyProducer(ITargetBlock<string> target)
{
    ...
    await target.SendAsync(..);
    ...
    target.Complete();
}

async Task MyConsumer(ISourceBlock<string> target)
{
    ...
    var message=await target.ReceiveAsync();
    ...
}

public static async Task Main()
{
    var buffer=new BufferBlock<string>();
    MyProducer(buffer);
    await MyConsumer(buffer);
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Thanks for the attention and effort. But my question about reading and writing batches of elements. I know about single element send/receive this methods described in article by link in my question. – gabba Sep 13 '18 at 20:41
  • 1
    @gabba Then you should use BatchBlock, not BufferBlock – Panagiotis Kanavos Sep 14 '18 at 06:51
  • thanks. Will use BatchBlock with BufferBlock as JSteward advised – gabba Sep 14 '18 at 08:53