Obie odpowiedzi nie wspomniały o oczekiwanym Task.WhenAll
:
var task1 = DoWorkAsync();
var task2 = DoMoreWorkAsync();
await Task.WhenAll(task1, task2);
Główna różnica między Task.WaitAll
i Task.WhenAll
polega na tym, że pierwsze blokuje (podobnie jak Wait
w przypadku pojedynczego zadania), podczas gdy drugie nie może i może być oczekiwane, dając kontrolę nad dzwoniącym, aż wszystkie zadania zakończą się.
Co więcej, obsługa wyjątków różni się:
Task.WaitAll
:
Przynajmniej jedna z instancji Zadania została anulowana lub zgłoszony został wyjątek podczas wykonywania co najmniej jednej z instancji Zadania. Jeśli zadanie zostało anulowane, AggregateException zawiera OperationCanceledException w kolekcji InnerExceptions.
Task.WhenAll
:
Jeśli którekolwiek z dostarczonych zadań zostaną zakończone w stanie błędu, zwrócone zadanie zostanie również ukończone w stanie Usterka, w którym jego wyjątki będą zawierać agregację zestawu nieopakowanych wyjątków z każdego z dostarczonych zadań.
Jeśli żadne z dostarczonych zadań nie spowodowało błędu, ale co najmniej jedno z nich zostało anulowane, zwrócone zadanie zakończy się w stanie Anulowane.
Jeśli żadne z zadań nie uległo awarii i żadne z zadań nie zostało anulowane, wynikowe zadanie zakończy się w stanie RanToCompletion. Jeśli podana tablica / wyliczenie nie zawiera żadnych zadań, zwrócone zadanie natychmiast przejdzie w stan RanToCompletion, zanim zostanie zwrócone do programu wywołującego.
await Task.WhenAll(task1, task2);
?Task.WhenAll
nie uruchamia zadań dla Ciebie. Musisz podać je jako „gorące”, co oznacza, że już się rozpoczęło.StartNew
i spinning nowych zadań ma wspólnego z asynchronicznym czekaniem na nich wszystkich?Możesz utworzyć wiele zadań, takich jak:
źródło
Najlepszą opcją, jaką widziałem, jest następująca metoda rozszerzenia:
Nazwij to tak:
Lub z asynchroniczną lambda:
źródło
Możesz użyć,
WhenAll
który zwróci oczekiwanyTask
lubWaitAll
który nie ma typu zwrotu i zablokuje dalsze wykonywanie kodu podobnie doThread.Sleep
momentu, aż wszystkie zadania zostaną zakończone, anulowane lub zakłócone.Przykład
Jeśli chcesz uruchomić zadania w praktycznej kolejności, możesz uzyskać inspirację z tego odpowiedzi .
źródło
await
za każdą operację i jednocześnie użyjWaitAll
lubWhenAll
. Czy zadaniaTask[]
inicjujące nie powinny być bezawait
?Czy chcesz
Task
połączyć łańcuchy , czy można je wywoływać równolegle?Do łączenia
Po prostu zrób coś takiego
i nie zapomnij sprawdzić poprzedniej
Task
instancji w każdej z nich,ContinueWith
ponieważ może to być wina.Dla równoległego sposobu
Najprostsza metoda, na którą natknąłem się: w
Parallel.Invoke
przeciwnym razieTask.WaitAll
możesz użyćWaitHandle
s do odliczania do zera akcji (poczekaj, jest nowa klasa:)CountdownEvent
lub ...źródło
Tak to robię za pomocą tablicy Func <> :
źródło
Jeszcze jedna odpowiedź ... ale zwykle znajduję się w przypadku, gdy muszę jednocześnie ładować dane i umieszczać je w zmiennych, takich jak:
źródło
LoadCatsAsync()
iLoadDogAsync()
to tylko połączenia z bazą danych, są one powiązane z operacjami we / wy.Task.Run()
jest przeznaczony do pracy z procesorem; dodaje dodatkowy niepotrzebny narzut, jeśli wszystko, co robisz, to czeka na odpowiedź z serwera bazy danych. Akceptowana odpowiedź Yuvala to właściwy sposób na pracę związaną z IO.Przygotowałem kawałek kodu, aby pokazać, jak korzystać z zadania w niektórych z tych scenariuszy.
źródło