2013-05-31 1 views
5

Ich habe diese einfache Schleife, die ich gerne deklarativ schreiben würde, mit LINQ.Async-Schleife in LINQ-Abfrage konvertieren

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; 
    } 

Ich wünsche etwas, das wie folgt aussieht: zusammen

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

Ich bin stecken, vor allem auf Herstellung von LINQ und async/await Arbeit.

+0

Sie können async auch in einem Lambda verwenden :) –

+0

installieren Sie Resharper und Sie können solche Schleifen in einen Lambda-Ausdruck konvertieren –

+0

@FabianBigler: Zeigen Sie uns, wie das in einer Antwort aussehen würde. –

Antwort

13

Ihre Optionen für async LINQ sind sehr begrenzt. Wie die andere Antwort darauf hingewiesen, können Sie asynchrone Methoden in Select verwenden, aber das ist es:

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

Dies Ihnen eine Folge von Task<Foo> erhalten. Anschließend können Sie erwarten für sie alle zu vervollständigen:

var results = await Task.WhenAll(tasks); 

Jetzt haben Sie eine Reihe von Foo, die gefiltert werden können:

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

Beachten Sie, dass dies hat ganz andere Semantik als Ihre ursprüngliche Code. Ihr ursprünglicher Code wird await jede Quelle vor Beginn der nächsten; Diese Antwort beginnt alle Quellen zu gehen, und dann await sie alle.

Wenn Sie foreach Semantik wollen und müssen await innerhalb der Schleife, dann die richtige Lösung ist, eine foreach Schleife eine await enthält, zu verwenden. Es gibt kein direktes LINQ-Äquivalent.