C#
Throw timing
Learn throw behavior before and after await.
Throw timing
A throw statement inside an async method does not fire immediately. The error is stored in the returned Task; it is rethrown when you await it. So var t = ThrowAsync(); does not throw; await t; does.
This requires care in fire-and-forget scenarios: writing ThrowAsync(); and ignoring it leaves the error in the Task, silently ignored. To catch the error, await the Task or check its Exception property.
When the exception fires
Knowing when the error fires is critical for debugging. An async method runs synchronously up to the first await. If a throw comes after an await, when the throw runs the error is stored in the Task.
The remaining code (after throw) does not run. If the caller awaits the Task, the throw fires; if not, it is silently ignored. So always await or monitor the Task.
Exercise Throw and catch
Define static async Task ThrowIfNegative(int n). In its body call await Task.CompletedTask;. If n < 0 throw new ArgumentException("Negative");. Make Main a static async Task Main. Catch the error with try { await ThrowIfNegative(-1); } catch (ArgumentException ex) { Console.WriteLine(ex.Message); } and print the message.
Show example solution
In ThrowIfNegative body write await Task.CompletedTask; and if (n < 0) throw new ArgumentException("Negative");. Make Main static async Task Main() and write try { await ThrowIfNegative(-1); } catch (ArgumentException ex) { Console.WriteLine(ex.Message); }
Example solution:
using System;
using System.Threading.Tasks;
class Program
{
static async Task ThrowIfNegative(int n)
{
await Task.CompletedTask;
if (n < 0)
{
throw new ArgumentException("Negative");
}
}
static async Task Main()
{
try
{
await ThrowIfNegative(-1);
}
catch (ArgumentException ex)
{
Console.WriteLine(ex.Message);
}
}
}
Test yourself
-
Match throw timing
- var t = ThrowAsync();
- Error not yet thrown
- await t;
- Error is thrown
- throw new Exception();
- Stores error in Task
- t.Exception
- Inspects the error
-
When does throw fire in an async method?
- At once, on the throw line
- When Main starts
- When awaited
- When Task.Dispose is called
Show answer
When awaited — Correct. In async methods, throw fires when awaited.
-
Complete the throw statement
static async Task Fail() { ____ new InvalidOperationException("Hata"); }
Show answer
static async Task Fail() { throw new InvalidOperationException("Hata"); }
Next lesson: Exception filtering