Czy można używać Async podczas korzystania z ForEach? Poniżej kod, który próbuję:
using (DataContext db = new DataLayer.DataContext())
{
db.Groups.ToList().ForEach(i => async {
await GetAdminsFromGroup(i.Gid);
});
}
Otrzymuję błąd:
Nazwa „Async” nie istnieje w obecnym kontekście
Metoda, w której zawarta jest instrukcja using, jest ustawiona na asynchroniczną.
c#
async-await
James Jeffery
źródło
źródło
List.ForEach()
nie jest częścią LINQ.async
. Byli bardzo pomocni!foreach
zawait
in your loop body.ForEach
przyjmuje tylko typ delegata synchronicznego i nie ma przeciążenia przyjmującego typ delegata asynchronicznego. Więc krótka odpowiedź brzmi: „nikt nie napisał asynchronicznegoForEach
”. Dłuższą odpowiedzią jest to, że musiałbyś przyjąć pewną semantykę; np. czy elementy powinny być przetwarzane pojedynczo (jakforeach
), czy jednocześnie (jakSelect
)? Jeśli pojedynczo, czy strumienie asynchroniczne nie byłyby lepszym rozwiązaniem? Jeśli jednocześnie, czy wyniki powinny być w oryginalnej kolejności, czy w kolejności ukończenia? Czy powinno zawieść przy pierwszym niepowodzeniu, czy też poczekać, aż wszystko się zakończy? Itd.SemaphoreSlim
do ograniczania zadań asynchronicznych.Ta mała metoda rozszerzenia powinna zapewnić bezpieczną dla wyjątków iterację asynchroniczną:
Ponieważ zmieniamy zwracany typ lambda z
void
naTask
, wyjątki będą propagowane poprawnie. To pozwoli ci napisać coś takiego w praktyce:źródło
async
powinno być wcześnieji =>
ForEachAsync
jest to metoda biblioteczna, więc oczekiwanie powinno być prawdopodobnie skonfigurowane zConfigureAwait(false)
.Prostą odpowiedzią jest użycie
foreach
słowa kluczowego zamiastForEach()
metodyList()
.źródło
Oto rzeczywista działająca wersja powyższych wariantów asynchronicznych dla wszystkich z przetwarzaniem sekwencyjnym:
Oto realizacja:
Jaka jest kluczowa różnica?
.ConfigureAwait(false);
który zachowuje kontekst głównego wątku podczas asynchronicznego sekwencyjnego przetwarzania każdego zadania.źródło
Począwszy od programu
C# 8.0
, możesz tworzyć i wykorzystywać strumienie asynchronicznie.Więcej
źródło
MoveNext
na moduł wyliczający. Jest to ważne w przypadkach, gdy moduł wyliczający nie może natychmiast pobrać następnego elementu i musi czekać, aż jeden stanie się dostępny.Dodaj tę metodę rozszerzenia
A następnie użyj w ten sposób:
źródło
Problem polegał na tym, że
async
słowo kluczowe musiało występować przed lambdą, a nie przed ciałem:źródło
async void
. To podejście ma problemy z obsługą wyjątków i wiedzą, kiedy operacje asynchroniczne zostaną ukończone.