2013-05-31 6 views
5

LINQを使用して宣言的に記述したいこの単純なループがあります。特に一緒にLINQとasync/await作品を作ることに、私はこだわっている非同期ループをLINQクエリに変換する

return FooSources.Where(...).FirstOrDefault(); 

async Task<Foo> GetFooAsync(string fooId, CancellationToken cancellationToken = default(CancellationToken)) 
    { 
     foreach (var source in FooSources) 
     { 
      var result = await source.GetFooAsync(fooId, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); 
      if (result != null) 
      { 
       return result; 
      } 
     } 
     return null; 
    } 

私はのようなものを望みます。

+0

ラムダでasyncを使用することもできます:) –

+0

resharperをインストールして、そのようなループをラムダ式に変換することができます –

+0

@FabianBigler:答えにどのようなものかを教えてください。 –

答えて

13

async LINQのオプションは非常に限られています。他の答えは指摘したように、あなたはSelectで非同期メソッドを使用することができますが、それはそれについてです:

var tasks = FooSources.Select(source => source.GetFooAsync(fooId, cancellationToken)); 

これは、あなたTask<Foo>のシーケンスを取得します。それらすべてが完了するのをあなたはその後、待つことができます。これはあなたの元のコードは非常に異なる意味を持っていることを

return results.Where(foo => foo != null); 

注:

var results = await Task.WhenAll(tasks); 

は今、あなたはフィルタリングすることができ Fooの配列を、持っています。元のコードは awaitになります。この回答はすべてのソースを開始し、次に awaitすべてを開始します。

あなたがforeachセマンティクスをしたいし、ループ内awaitに必要がある場合は、正しい解決策はawaitを含むforeachループを使用することです。直接LINQに相当するものはありません。