Summary - Async exceptions
Combine try/catch, AggregateException and when to write a robust async wrapper.
Summary - Async exceptions
In this group you learned the basics of async error handling: async try/catch works like sync; await is required to catch. AggregateException bundles parallel errors; Task.Exception inspects the error. throw does not fire at once but when awaited.
Finally you learned to filter catch blocks with the when clause. Now we will combine all of this in a small app.
Exercise Combine try/catch with WhenAll
Define static async Task FailAsync(). In its body write await Task.CompletedTask; and throw new InvalidOperationException("Error");. Make Main a static async Task Main. Print the first error message with try { await Task.WhenAll(FailAsync(), FailAsync()); } catch (Exception ex) { Console.WriteLine(ex.Message); }.
Show example solution
In FailAsync body write await Task.CompletedTask; and throw new InvalidOperationException("Error");. Make Main static async Task Main() and write try { await Task.WhenAll(FailAsync(), FailAsync()); } catch (Exception ex) { Console.WriteLine(ex.Message); }
Example solution:
using System;
using System.Threading.Tasks;
class Program
{
static async Task FailAsync()
{
await Task.CompletedTask;
throw new InvalidOperationException("Error");
}
static async Task Main()
{
try
{
await Task.WhenAll(FailAsync(), FailAsync());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Tips
A few tips: always use await for async error catching. Iterate AggregateException with InnerExceptions. Inspect a Task's error without awaiting via Task.Exception.
Use the when clause for exception filtering; avoid side effects. For multiple parallel errors, look at WhenAll's AggregateException. Avoid fire-and-forget; await or monitor every Task.
Exercise Mini app: Invalid input
Define static async Task<int> ParseOrThrow(string s). In its body call await Task.CompletedTask;. If int.TryParse(s, out int n) is true return n;, otherwise throw new FormatException("Invalid");. Make Main a static async Task Main. Catch the error with try { int n = await ParseOrThrow("abc"); } catch (FormatException ex) { Console.WriteLine(ex.Message); } and print it.
Show example solution
In ParseOrThrow body write await Task.CompletedTask; if (int.TryParse(s, out int n)) return n; else throw new FormatException("Invalid");. Make Main static async Task Main() and write try { int n = await ParseOrThrow("abc"); } catch (FormatException ex) { Console.WriteLine(ex.Message); }
Example solution:
using System;
using System.Threading.Tasks;
class Program
{
static async Task<int> ParseOrThrow(string s)
{
await Task.CompletedTask;
if (int.TryParse(s, out int n))
{
return n;
}
throw new FormatException("Invalid");
}
static async Task Main()
{
try
{
int n = await ParseOrThrow("abc");
}
catch (FormatException ex)
{
Console.WriteLine(ex.Message);
}
}
}
Test yourself
-
What is required to catch the error?
- Use await
- Use async void
- Thread.Sleep
- Task.Delay
Show answer
Use await — Correct. You must use await to catch the error.