3

When consuming IAsyncEnumerable<T>, is it possible to just read first item from the stream and then cancel the operation and return it? Something like a FirstOrDefault on IEnumerable<T>?

Cheers

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Branislav B.
  • 509
  • 7
  • 21

2 Answers2

5

LINQ operators over IAsyncEnumerable are provided through the System.Linq.Async package.

var discount=await priceStream.FirstOrDefaultAsync(it=>it.Price<cutoff);

Be careful though. With an async stream, you don't know whether there are any matching elements until the stream itself closes or you cancel waiting. A matching item may appear in 10 seconds, 1 day or never. That's why you typically need to pass a cancellation token too, so you can stop awaiting after a while:

var cts=new CancellationSource(TimeSpan.FromMinutes(1));
var discount=await priceStream.FirstOrDefaultAsync(
    it=>it.Price<cutoff,
    cts.Token);

The System.Linq.Async operators allow using asynchronous predicates too :

var discount=await priceStream.FirstOrDefaultAsync(
    async it => await service.IsGoodOfferAsync(it),
    cts.Token);
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
3

See this Microsoft Tutorial on using IAsyncEnumerable<T>. You can get the IAsyncEnumerator<T> and use it to get the first item.

using (var enumerator = myAsyncEnumerable.GetAsyncEnumerator()){
    // If MoveNextAsync() returns false, the enumerator is empty.
    var first = await enumerator.MoveNextAsync() ? enumerator.Current : default;
}