异常不可避免,所有地方都写try...catch也麻烦,所以有了未处理异常的处理的东东,分别为以下三个事件:
- Application.Current.DispatcherUnhandledException:DispatcherUnhandledException is raised by an Application for each exception that is unhandled by code running on the main UI thread.(UI线程中任何未处理的异常将触发该事件)
- System.Threading.Tasks.TaskScheduler.UnobservedTaskException:Occurs when a faulted task's unobserved exception is about to trigger exception escalation policy(出错的任务中未观察到的异常将触发该事件)。在Task被垃圾回收的时候,析构函数检测到该Task对象还有未被处理过的异常,会抛出这个异常并触发,所以感觉总是慢一拍。
- AppDomain.CurrentDomain.UnhandledException:应用程序域的未处理异常
第1、2个事件很好理解,在UI线程和任务线程throw new Excepiton("测试")都能测试出来,第3个事件我是折腾好久才找到触发的地方——比如在1、2事件的方法中又发生了异常,所以也可以理解1、2事件都有参数和方法可以设置成已处理(e.Handled=True、e.SetObserved()),第3个事件一被触发,game over。
最后附上我的代码
using System;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace L3_Exception
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
/// <summary>
/// 非主线程错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (Exception item in e.Exception.InnerExceptions)
{
sb.AppendLine($@"异常类型:{item.GetType()}
异常内容:{item.Message}
来自:{item.Source}
{item.StackTrace}");
}
e.SetObserved();
Restart("Task Exception", sb.ToString());
}
/// <summary>
/// App里面的错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
try
{
Exception ex = e.ExceptionObject as Exception;
sb.AppendLine($@"异常类型:{ ex.GetType()}
异常内容:{ ex.Message}
内部异常内容:{ex?.InnerException?.Message}
来自:{ ex.Source}
{ ex.StackTrace}");
}
catch
{
sb.AppendLine("不可恢复的WPF窗体线程异常");
}
Restart("Domain Exception", sb.ToString());
}
/// <summary>
/// 主线程错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($@"异常类型:{ e.Exception.GetType()}
异常内容:{ e.Exception.Message}
内部异常内容:{e.Exception?.InnerException?.Message}
来自:{ e.Exception.Source}
{ e.Exception.StackTrace}");
e.Handled = true;
Restart("主线程异常", sb.ToString());
}
private static void Restart(string title, string content)
{
MessageBox.Show(content, title);
//Current.Dispatcher.Invoke(() => Current.Shutdown(-1));
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
2014-03-04 第二课 两个视图+数据传输
2014-03-04 第一课 Hello