C# 多线程 04-使用任务平行库 07-处理任务中的异常
🏷️ 《C# 多线程》
处理任务中的异常
csharp
/// <summary>
/// 处理任务中的异常
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Task<int> task;
try
{
task = Task.Run(() => TaskMethod("Task 1", 2));
// 尝试同步获取 task 的结果
// 捕获的异常是一个被封装的异常(AggregateExcption),可以访问 InnerException 获取底层异常
int result = task.Result;
Console.WriteLine($"Result: {result}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception caught: {ex}");
}
Console.WriteLine("----------------------------------------");
Console.WriteLine();
try
{
task = Task.Run(() => TaskMethod("Task 2", 2));
// 使用 GetAwaiter 和 GetResult 方法获取任务结果
// 这种情况下不会封装异常,因为 TPL 基础设施会提取该异常。
// 如果只有一个底层任务,那么一次只能获取一个原始异常。
int result = task.GetAwaiter().GetResult();
Console.WriteLine($"Result: {result}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception caught: {ex}");
}
Console.WriteLine("----------------------------------------");
Console.WriteLine();
var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
var t2 = new Task<int>(() => TaskMethod("Task 4", 2));
var complexTask = Task.WhenAll(t1, t2);
// 待 t1 和 t2 都结束后才会打印异常
// 异常类型为 AggregateExcption,其内部封装了 2 个任务抛出的异常
var exceptionHandler = complexTask.ContinueWith(
t => Console.WriteLine($"Exception caught: {t.Exception}"),
TaskContinuationOptions.OnlyOnFaulted);
t1.Start();
t2.Start();
Thread.Sleep(TimeSpan.FromSeconds(5));
Console.ReadLine();
}
static int TaskMethod(string name, int seconds)
{
Console.WriteLine($"Task {name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}. " +
$"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
throw new Exception("Boom!");
return 42 * seconds;
}
打印结果
txt
Task Task 1 is running on a thread id 3. Is thread pool thread: True
Exception caught: System.AggregateException: 发生一个或多个错误。 ---> System.Ex
ception: Boom!
在 Recipe4_7.Program.TaskMethod(String name, Int32 seconds) 位置 C:\Users\liu
jiajia\Source\Repos\learn-multi-threading\Recipe4-7\Program.cs:行号 63
在 Recipe4_7.Program.<>c.<Main>b__0_0() 位置 C:\Users\liujiajia\Source\Repos\
learn-multi-threading\Recipe4-7\Program.cs:行号 18
在 System.Threading.Tasks.Task`1.InnerInvoke()
在 System.Threading.Tasks.Task.Execute()
--- 内部异常堆栈跟踪的结尾 ---
在 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceled
Exceptions)
在 System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotifica
tion)
在 System.Threading.Tasks.Task`1.get_Result()
在 Recipe4_7.Program.Main(String[] args) 位置 C:\Users\liujiajia\Source\Repos
\learn-multi-threading\Recipe4-7\Program.cs:行号 20
---> (内部异常 #0) System.Exception: Boom!
在 Recipe4_7.Program.TaskMethod(String name, Int32 seconds) 位置 C:\Users\liu
jiajia\Source\Repos\learn-multi-threading\Recipe4-7\Program.cs:行号 63
在 Recipe4_7.Program.<>c.<Main>b__0_0() 位置 C:\Users\liujiajia\Source\Repos\
learn-multi-threading\Recipe4-7\Program.cs:行号 18
在 System.Threading.Tasks.Task`1.InnerInvoke()
在 System.Threading.Tasks.Task.Execute()<---
----------------------------------------
Task Task 2 is running on a thread id 4. Is thread pool thread: True
Exception caught: System.Exception: Boom!
在 Recipe4_7.Program.TaskMethod(String name, Int32 seconds) 位置 C:\Users\liu
jiajia\Source\Repos\learn-multi-threading\Recipe4-7\Program.cs:行号 63
在 Recipe4_7.Program.<>c.<Main>b__0_1() 位置 C:\Users\liujiajia\Source\Repos\
learn-multi-threading\Recipe4-7\Program.cs:行号 32
在 System.Threading.Tasks.Task`1.InnerInvoke()
在 System.Threading.Tasks.Task.Execute()
--- 引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServ