2013-05-31 13 views
5

Mam tę prostą pętlę, którą chciałbym napisać deklaratywnie, używając LINQ.Konwertuj pętlę asynchroniczną do zapytania LINQ

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

życzę czegoś, co wygląda jak:

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

utknąłem, w szczególności na podejmowaniu LINQ i async/await współpracować.

+0

Możesz użyć async w lambda też :) –

+0

zainstalować resharper i możesz przekonwertować takie pętle na wyrażenie lambda –

+0

@FabianBigler: Pokaż nam, jak to będzie wyglądać, w odpowiedzi. –

Odpowiedz

13

Twoje opcje dla async LINQ są bardzo ograniczone. Jako druga odpowiedź wskazał, można użyć metody async w Select, ale to o tym:

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

To będzie Ci sekwencję Task<Foo>. Następnie można oczekiwać dla nich wszystko, aby zakończyć:

var results = await Task.WhenAll(tasks); 

Teraz masz tablicę Foo, które mogą być filtrowane:

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

pamiętać, że ta ma bardzo różne semantykę niż oryginalnego kodu. Twój oryginalny kod będzie await każde źródło przed rozpoczęciem następnego; ta odpowiedź rozpocznie wszystkie źródła, a następnie wszystkie.

Jeśli chcesz foreach semantykę i trzeba await wewnątrz pętli, a następnie poprawnym rozwiązaniem jest użycie foreach pętlę zawierającą await. Nie ma bezpośredniego odpowiednika LINQ.

Powiązane problemy