Last active
April 11, 2020 08:57
-
-
Save waf/9463677904d7063be9466322fa9aa7b5 to your computer and use it in GitHub Desktop.
Various ways of using async/await and their end result
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Threading.Tasks; | |
namespace AsyncPatterns | |
{ | |
public class Program | |
{ | |
public static async Task Main(string[] args) | |
{ | |
await SerialTasks(); | |
// the following two are equivalent | |
await ConcurrentTasks(); | |
await ConcurrentTasksWithLinq(); | |
await ConcurrentTasksWithLinqAwait(); | |
// you probably don't want this... | |
TasksWithoutAwait(); | |
// The following are not shown: | |
// Task.WaitAll, Task.WaitAny, task.Result, task.Wait(), task.GetAwaiter().GetAwaiter().GetResult() | |
// because you don't want to use them unless you really know what you're doing: | |
} | |
private static async Task<string> SlowPrintAsync(string value) | |
{ | |
await Task.Delay(TimeSpan.FromSeconds(2)); | |
Console.WriteLine(value); | |
return value; | |
} | |
private static async Task SerialTasks() | |
{ | |
var stopwatch = Stopwatch.StartNew(); | |
string a = await SlowPrintAsync("a"); | |
string b = await SlowPrintAsync("b"); | |
Print(stopwatch.Elapsed, a, b); | |
//PRINTS: | |
// a | |
// b | |
// a b in 4 seconds | |
} | |
private static async Task ConcurrentTasks() | |
{ | |
var stopwatch = Stopwatch.StartNew(); | |
Task<string> aTask = SlowPrintAsync("a"); | |
Task<string> bTask = SlowPrintAsync("b"); | |
string[] values = await Task.WhenAll(aTask, bTask); | |
Print(stopwatch.Elapsed, values); | |
//PRINTS: | |
// a | |
// b | |
// a b in 2 seconds | |
//OR | |
// b | |
// a | |
// a b in 2 seconds | |
} | |
private static async Task ConcurrentTasksWithLinq() | |
{ | |
var stopwatch = Stopwatch.StartNew(); | |
Task<string>[] tasks = new[] { "a", "b" } | |
.Select(value => SlowPrintAsync(value)) | |
.ToArray(); | |
string[] values = await Task.WhenAll(tasks); | |
Print(stopwatch.Elapsed, values); | |
//PRINTS: | |
// a | |
// b | |
// a b in 2 seconds | |
//OR | |
// b | |
// a | |
// a b in 2 seconds | |
} | |
private static async Task ConcurrentTasksWithLinqAwait() | |
{ | |
var stopwatch = Stopwatch.StartNew(); | |
Task<string>[] tasks = new[] { "a", "b" } | |
// the `await` below is not needed, but if we wanted | |
// a try/catch inside the lambda, we would need it. | |
.Select(async value => await SlowPrintAsync(value)) | |
.ToArray(); | |
string[] values = await Task.WhenAll(tasks); | |
Print(stopwatch.Elapsed, values); | |
//PRINTS: | |
// a | |
// b | |
// a b in 2 seconds | |
//OR | |
// b | |
// a | |
// a b in 2 seconds | |
} | |
private static void TasksWithoutAwait() | |
{ | |
Task<string> a = SlowPrintAsync("a"); | |
Task<string> b = SlowPrintAsync("b"); | |
// doesn't print anything, program exits before tasks finish | |
} | |
private static void Print(TimeSpan elapsedTime, params string[] values) => | |
Console.WriteLine( | |
string.Join(" ", values) | |
+ $" in {elapsedTime.Seconds} seconds" | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment