Skip to content

Instantly share code, notes, and snippets.

@waf
Last active April 11, 2020 08:57
Show Gist options
  • Save waf/9463677904d7063be9466322fa9aa7b5 to your computer and use it in GitHub Desktop.
Save waf/9463677904d7063be9466322fa9aa7b5 to your computer and use it in GitHub Desktop.
Various ways of using async/await and their end result
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