Jaka jest różnica pomiędzy Task.WaitAll()i Task.WhenAll()od Async CTP? Czy możesz podać przykładowy kod ilustrujący różne przypadki użycia?
Jaka jest różnica pomiędzy Task.WaitAll()i Task.WhenAll()od Async CTP? Czy możesz podać przykładowy kod ilustrujący różne przypadki użycia?
Odpowiedzi:
Task.WaitAll blokuje bieżący wątek, dopóki wszystko się nie zakończy.
Task.WhenAllzwraca zadanie reprezentujące akcję czekania, aż wszystko się zakończy.
Oznacza to, że z metody asynchronicznej możesz użyć:
await Task.WhenAll(tasks);
... co oznacza, że twoja metoda będzie kontynuowana, gdy wszystko się skończy, ale do tego czasu nie będziesz wiązać nici, żeby się po prostu zawiesić.
WhenAll, ale to nie to samo, co blokowanie wątku.
Podczas gdy odpowiedź JonSkeeta wyjaśnia różnicę w typowo doskonały sposób, istnieje jeszcze jedna różnica: obsługa wyjątków .
Task.WaitAllrzuca AggregateExceptionkiedy rzuca dowolne z zadań i możesz sprawdzić wszystkie zgłoszone wyjątki. Opcja awaitin await Task.WhenAllrozpakowuje AggregateExceptioni „zwraca” tylko pierwszy wyjątek.
Gdy program poniżej zostanie wykonany z await Task.WhenAll(taskArray)danymi wyjściowymi, jest on następujący.
19/11/2016 12:18:37 AM: Task 1 started
19/11/2016 12:18:37 AM: Task 3 started
19/11/2016 12:18:37 AM: Task 2 started
Caught Exception in Main at 19/11/2016 12:18:40 AM: Task 1 throwing at 19/11/2016 12:18:38 AM
Done.
Gdy poniższy program jest wykonywany z Task.WaitAll(taskArray)danymi wyjściowymi, jest on następujący.
19/11/2016 12:19:29 AM: Task 1 started
19/11/2016 12:19:29 AM: Task 2 started
19/11/2016 12:19:29 AM: Task 3 started
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 1 throwing at 19/11/2016 12:19:30 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 2 throwing at 19/11/2016 12:19:31 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 3 throwing at 19/11/2016 12:19:32 AM
Done.
Program:
class MyAmazingProgram
{
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{ }
}
static void WaitAndThrow(int id, int waitInMs)
{
Console.WriteLine($"{DateTime.UtcNow}: Task {id} started");
Thread.Sleep(waitInMs);
throw new CustomException($"Task {id} throwing at {DateTime.UtcNow}");
}
static void Main(string[] args)
{
Task.Run(async () =>
{
await MyAmazingMethodAsync();
}).Wait();
}
static async Task MyAmazingMethodAsync()
{
try
{
Task[] taskArray = { Task.Factory.StartNew(() => WaitAndThrow(1, 1000)),
Task.Factory.StartNew(() => WaitAndThrow(2, 2000)),
Task.Factory.StartNew(() => WaitAndThrow(3, 3000)) };
Task.WaitAll(taskArray);
//await Task.WhenAll(taskArray);
Console.WriteLine("This isn't going to happen");
}
catch (AggregateException ex)
{
foreach (var inner in ex.InnerExceptions)
{
Console.WriteLine($"Caught AggregateException in Main at {DateTime.UtcNow}: " + inner.Message);
}
}
catch (Exception ex)
{
Console.WriteLine($"Caught Exception in Main at {DateTime.UtcNow}: " + ex.Message);
}
Console.WriteLine("Done.");
Console.ReadLine();
}
}
await t1; await t2; await t3;vsawait Task.WhenAll(t1,t2,t3);
await, a nie różnicę między tymi dwiema metodami. Obie propagują AggregateException, rzucając bezpośrednio lub przez właściwość ( Task.Exceptionwłaściwość).
Jako przykład różnicy - jeśli masz zadanie, robi coś z wątkiem interfejsu użytkownika (np. Zadanie reprezentujące animację w serii ujęć), jeśli Task.WaitAll()następnie wątek interfejsu jest zablokowany, a interfejs użytkownika nigdy nie jest aktualizowany. jeśli używasz, await Task.WhenAll()to wątek interfejsu użytkownika nie jest blokowany, a interfejs użytkownika zostanie zaktualizowany.
Co oni robią:
Co za różnica:
Użyj, gdy:
WaitAlljak rozumiem.
Task.WaitAll po wykonaniu innej pracy? Mam na myśli, zamiast nazywać go zaraz po rozpoczęciu zadań.