Jeśli nie wiadomo - warto poeksperymentować.
W przypadku **multiple awaits **
- kod wykonuje się sekwencyjnie
private static async Task Main(string[] args)
{
await FirstTask();
await SecondTask();
Console.ReadKey();
}
private static async Task FirstTask()
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"From {nameof(FirstTask)}");
await Task.Delay(1000);
}
}
private static async Task SecondTask()
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"From {nameof(SecondTask)}");
await Task.Delay(1000);
}
}
Wynik:
From FirstTask
From FirstTask
From FirstTask
From FirstTask
From FirstTask
From SecondTask
From SecondTask
From SecondTask
From SecondTask
From SecondTask
w przypadku WhenAll
- kod wykonuje się równolegle
await Task.WhenAll(FirstTask(), SecondTask());
Wynik:
From FirstTask
From SecondTask
From SecondTask
From FirstTask
From SecondTask
From FirstTask
From FirstTask
From SecondTask
From FirstTask
From SecondTask
W przypadku **multiple awaits **
3) mogę stracić wyjątki gdy poleciały we wczesniejszym await
private static async Task Main(string[] args)
{
await FirstTask();
await SecondTask();
Console.ReadKey();
}
private static async Task FirstTask()
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"From {nameof(FirstTask)}");
await Task.Delay(100);
if (i == 3)
{
throw new Exception("some exception");
}
}
}
private static async Task SecondTask()
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"From {nameof(SecondTask)}");
await Task.Delay(100);
}
}
Dostaję wyjątek (nieopakowany w AggregateException
) natychmiast po jego wystąpieniu. Kończy wykonywanie programu.
w przypadku WhenAll
4) nawet gdy będzie exception to nie zatrzyma to egzekucji tasków
await Task.WhenAll(FirstTask(), SecondTask());
Dostaję wyjątek (nieopakowany w AggregateException
) natychmiast po jego wystąpieniu. Kończy wykonywanie programu.
w przypadku WhenAll
2) nie ma pewności, który task będzie wykonany pierwszy - więc jeśli jeden zalezy od drugiego, to WhenAll nie jest najlepszym pomysłem
private static Random Rand = new Random(DateTime.Now.Millisecond);
private static async Task Main(string[] args)
{
var t1 = FirstTask()
.ContinueWith(t => Console.WriteLine("First completed"), TaskContinuationOptions.OnlyOnRanToCompletion);
var t2 = SecondTask()
.ContinueWith(t => Console.WriteLine("Second completed"), TaskContinuationOptions.OnlyOnRanToCompletion);
await Task.WhenAll(t1, t2);
Console.ReadKey();
}
private static async Task FirstTask()
{
var time = Rand.Next(1, 5) * 1000;
await Task.Delay(time);
}
private static async Task SecondTask()
{
var time = Rand.Next(1, 5) * 1000;
await Task.Delay(time);
}
Wynik:
Czasami First completed, Second completed
, czasami na odwrót.