示例:一个扔异常的异步方法
static async Task ThrowAfter(int ms, string message)
{
await Task.Delay(ms);
throw new Exception(message);
}
示例:不await,捕获不到异常
- 没有
await 异步方法ThrowAfter()
- 在
ThrowAfter()抛出异常之前,其调用者,DontHandle() 已经执行完毕
- 所以
try-catch,也捕获不到异常
private static void DontHandle()
{
try
{
#pragma warning disable CS4014
ThrowAfter(200, "first");
#pragma warning restore CS4014
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
示例:await,捕获异常
private static async void HandleOneError()
{
try
{
await ThrowAfter(2000, "first");
}
catch (Exception ex)
{
Console.WriteLine($"handled {ex.Message}");
}
}
示例:多个异步方法都会扔异常,但这么实现,有的不执行
private static async void StartTwoTasks()
{
try
{
await ThrowAfter(2000, "first");
await ThrowAfter(1000, "second");
}
catch (Exception ex)
{
Console.WriteLine($"handled {ex.Message}");
}
}
示例: 多个异步方法都会扔异常,这么实现,所有异步方法都能执行,但只能捕获第一个异步方法的异常
- 通过
await Task.WhenAll(t1, t2);
private async static void StartTwoTasksParallel()
{
Task t1 = null;
try
{
t1 = ThrowAfter(2000, "first");
Task t2 = ThrowAfter(1000, "second");
await Task.WhenAll(t1, t2);
}
catch (Exception ex)
{
Console.WriteLine($"handled {ex.Message}");
}
}
示例:多个异步方法都会扔异常,这么实现,所有异步方法都能执行,并且能观察到所有异步方法抛出的异常
- 通过
Task的Exception.InnerExceptions可以看到两个ThrowAfter()扔的异常
- 另外还可以通过
Task的属性IsFaulted来检查,是否出错。如果任务有异常,IsFaulted会是true
private static async void ShowAggregatedException()
{
Task taskResult = null;
try
{
Task t1 = ThrowAfter(2000, "first");
Task t2 = ThrowAfter(1000, "second");
await (taskResult = Task.WhenAll(t1, t2));
}
catch (Exception ex)
{
Console.WriteLine($"handled {ex.Message}");
foreach (var ex1 in taskResult.Exception.InnerExceptions)
{
Console.WriteLine($"inner exception {ex1.Message} from task {ex1.Source}");
}
}
}