【多线程笔记】捕获Task异常的几种方式
前言
在线程执行的地方使用try..catch..捕获不到异常
首先,线程内部不应该出现异常,所以首选处理方式是在Task中使用try..catch..把异常处理掉
Task中可能会抛出多个异常,应该使用AggregateException捕获多线程中所有异常。AggregateException是一个集合
wait()、Result
在调用Task的Wait()方法或Result属性处会抛出Task中的异常。
Wait() 和 Task.Result 抛出的异常包在AggregateException中。如果使用await则不会包在AggregateException中
static void Main(string[] args)
{
try
{
Task.Run(() => { throw new Exception("error!!"); }).Wait();
}
catch (Exception aggregateException)
{
var e = aggregateException is AggregateException;//true
var ex = aggregateException.InnerException;
}
}
以下方式抛出的异常也不会包在AggregateException中
try
{
Task.Run(() => { throw new Exception("error!!"); }).GetAwaiter().GetResult();
}
catch (Exception exception)
{
var e = exception is AggregateException;//false
}
使用ContinueWith捕获异常
如果不可以在内部捕获,可以使用ContinueWith()方法捕获异常
var t = Task.Run<int>(() =>
{
throw new Exception("error");
Console.WriteLine("action do do do");
return 1;
}).ContinueWith<Task<int>>((t1) => {
if (t1 != null && t1.IsFaulted)
{
Console.WriteLine(t1.Exception.Message); //记录异常日志
}
return t1;
}).Unwrap<int>();
上面使用起来比较麻烦,添加一个扩展方法:
public static Task Catch(this Task task)
{
return task.ContinueWith<Task>(delegate(Task t)
{
if (t != null && t.IsFaulted)
{
AggregateException exception = t.Exception;
Trace.TraceError("Catch exception thrown by Task: {0}", new object[]
{
exception
});
}
return t;
}).Unwrap();
}
public static Task<T> Catch<T>(this Task<T> task)
{
return task.ContinueWith<Task<T>>(delegate(Task<T> t)
{
if (t != null && t.IsFaulted)
{
AggregateException exception = t.Exception;
Trace.TraceError("Catch<T> exception thrown by Task: {0}", new object[]
{
exception
});
}
return t;
}).Unwrap<T>();
}
捕获全局未观察到的异常
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs e)=> {
Console.WriteLine("捕获异常,"+e.Exception.InnerException.Message);
};
如何捕获async..await..异常:
try{
await task1;
}
catch{
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构