LINQで非同期ラムダを待機する
System.Linq.Asyncのバージョン4.0.0で、LINQの各メソッドに非同期ラムダを受けて待機するバリエーションである~Awaitシリーズが追加された。以前までは自分で用意する必要があって微妙でIssueもいくつか立っていたが、パッケージに含まれるようになったので楽!
例)
var array = new[] { 1, 2, 3 }; var tasks = array.Select((x) => GetAsync(x)); // Task.WhenAll(tasks) ...
みたいな書き方をすると、非同期ラムダ式の戻り型はTaskなので、複数のTaskが生成されてGetAsyncが全て並列に動く(正確にはawaitのタイミングでTaskが返って次が走り始める)。これを、1つずつ直列にただし非同期で動かしたいとする。
var array = new[] { 1, 2, 3 }; var tasks = array.Select((x) => GetAsync(x)); foreach (var task in tasks) { var value = await task; // ... }
これだけならTaskを1つずつawaitすれば事足りる。しかしSelectの後段でLINQメソッドをつなげたい場合はIAsyncEnumerable
var array = new[] { 1, 2, 3 }; var values = array .ToAsyncEnumerable() .SelectAwait(async (x) => await GetAsync(x)) .ToArray();
以前の自前実装したものとSelectAwaitを使ったものと、両方こちらの回答に書いた。
SelectAwaitに限らず、ForEachAwaitAsyncなどIAsyncEnumerable