C# 多线程 05-使用 C#6.0 05-处理异步操作中的异常
🏷️ 《C# 多线程》
处理异步操作中的异常
csharp
/// <summary>
/// 处理异步操作中的异常
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
Console.ReadLine();
}
static async Task AsynchronousProcessing()
{
Console.WriteLine("1. 单个异常");
Console.WriteLine(" 使用 try/catch 捕获单个异常");
try
{
string result = await GetInfoAsync("任务 1", 2);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine($"Exception details: {ex}");
}
Console.WriteLine();
Console.WriteLine("2. 多个异常");
Console.WriteLine(" 尝试使用 try/catch 捕获多个异常,但此种写法仅能捕获其中一个异常");
Task<string> t1 = GetInfoAsync("任务 1", 3);
Task<string> t2 = GetInfoAsync("任务 2", 2);
try
{
string[] results = await Task.WhenAll(t1, t2);
Console.WriteLine(results.Length);
}
catch (Exception ex)
{
Console.WriteLine($"Exception details: {ex}");
}
Console.WriteLine();
Console.WriteLine("3. 使用 AggregateException 捕获多个异常");
Console.WriteLine(" 从 task 的 Exception 属性中获取多个异常的信息");
t1 = GetInfoAsync("任务 1", 3);
t2 = GetInfoAsync("任务 2", 2);
Task<string[]> t3 = Task.WhenAll(t1, t2);
try
{
string[] results = await t3;
Console.WriteLine(results.Length);
}
catch
{
var ae = t3.Exception.Flatten();
var exceptions = ae.InnerExceptions;
Console.WriteLine($"Exceptions caght: {exceptions.Count}");
foreach (var e in exceptions)
{
Console.WriteLine($"Exception details: {e}");
Console.WriteLine();
}
}
Console.WriteLine();
Console.WriteLine("4. 在 catch 和 finally 块中使用 await");
Console.WriteLine(" c#6.0中,允许在catch和finally块中使用await,在之前的版本中这种写法会报错");
Console.WriteLine(" 若将语言版本改为C#5.0编译,则会报如下错误:");
Console.WriteLine(" CS1985 无法在 catch 子句中等待");
Console.WriteLine(" CS1984 无法在 finally 子句体中等待");
try
{
string result = await GetInfoAsync("任务 1", 2);
Console.WriteLine(result);
}
catch (Exception ex)
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine($"Catch block with await: Exception details: {ex}");
}
finally
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.Write("Finally block");
}
}
static async Task<string> GetInfoAsync(string name, int seconds)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
throw new Exception($"Boom from {name}");
}
打印结果
txt
1. 单个异常
使用try/catch捕获单个异常
Exception details: System.Exception: Boom from 任务 1
在 Recipe5_5.Program.<GetInfoAsync>d__2.MoveNext() 位置 C:\Users\liujiajia\So
urce\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 101
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在 Recipe5_5.Program.<AsynchronousProcessing>d__1.MoveNext() 位置 C:\Users\li
ujiajia\Source\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 26
2. 多个异常
尝试使用try/catch捕获多个异常,但此种写法仅能捕获其中一个异常
Exception details: System.Exception: Boom from 任务 1
在 Recipe5_5.Program.<GetInfoAsync>d__2.MoveNext() 位置 C:\Users\liujiajia\So
urce\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 101
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在 Recipe5_5.Program.<AsynchronousProcessing>d__1.MoveNext() 位置 C:\Users\li
ujiajia\Source\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 42
3. 使用AggregateException捕获多个异常
从task的Exception属性中获取多个异常的信息
Exceptions caght: 2
Exception details: System.Exception: Boom from 任务 1
在 Recipe5_5.Program.<GetInfoAsync>d__2.MoveNext() 位置 C:\Users\liujiajia\So
urce\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 101
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在 Recipe5_5.Program.<AsynchronousProcessing>d__1.MoveNext() 位置 C:\Users\li
ujiajia\Source\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 59
Exception details: System.Exception: Boom from 任务 2
在 Recipe5_5.Program.<GetInfoAsync>d__2.MoveNext() 位置 C:\Users\liujiajia\So
urce\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 101
4. 在catch和finally块中使用await
c#6.0中,允许在catch和finally块中使用await,在之前的版本中这种写法会报错
若将语言版本改为C#5.0编译,则会报如下错误:
CS1985 无法在 catch 子句中等待
CS1984 无法在 finally 子句体中等待
Catch block with await: Exception details: System.Exception: Boom from 任务 1
在 Recipe5_5.Program.<GetInfoAsync>d__2.MoveNext() 位置 C:\Users\liujiajia\So
urce\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 101
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在 Recipe5_5.Program.<AsynchronousProcessing>d__1.MoveNext() 位置 C:\Users\li
ujiajia\Source\Repos\learn-multi-threading\Recipe5-5\Program.cs:行号 83
Finally block