参考链接:
Application.ThreadException Event (System.Windows.Forms) | Microsoft Learn
由于作者水平有限,如有写得不对的地方请指正
捕获程序的全局异常信息是为了记录类似系统突然崩溃或者内存溢出等异常信息到日志中,方便后续查找问题
在我们公司的系统中,也可以看到类似的处理逻辑,如下图:
具体的注册事件方法就不能放出来了
1 记录UI线程的异常信息可以通过Application.ThreadException事件
2 记录非UI线程的异常信息可以通过AppDomain.CurrentDomain.UnhandledException事件
一 Application.ThreadException测试操作步骤如下:
1 新建winform程序,并拖拽一个button到窗体中,button的事件代码如下:
private void button1_Click(object sender, EventArgs e)
{
throw new Exception("测试抛出异常");
}
如果在程序中没有注册Application.ThreadException事件,点击button后,会出现如下图的异常信息:
弹出上述的提示信息,用户的体验极其不好,这样我们就需要捕获到这个异常信息并进行相应的处理,如记录日志并在合适的地方显示错误信息
2 在winform的Program主方法中加入Application.ThreadException事件注册方法,代码如下:
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
//1记录日志信息
Exception ex = e.Exception;
//2 弹出提示
MessageBox.Show(string.Format("Application_ThreadException捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}", ex.GetType(), ex.Message, ex.StackTrace));
}
}
再次运行结果如下:
叉掉提示框后,程序正常运行
不过需要注意的是,当在界面渲染完毕前有异常信息,该事件就无效了,如把Program主方法的代码修改为:
[STAThread]
static void Main()
{
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
bool flag = true;
if (flag)
{
throw new Exception("主方法前加入测试异常信息抛出");
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
运行后,发现,连界面都出不来了
二 AppDomain.CurrentDomain.UnhandledException事件测试步骤如下:
1 新建winform程序,并拖拽一个button到窗体中,button的事件代码如下:
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(()=> {
throw new Exception("测试抛出异常");
});
thread.Start();
}
2 编辑Program主方法的代码如下:
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//1 记录日志
Exception ex = e.ExceptionObject as Exception;
//2 弹出提示信息
MessageBox.Show(string.Format("CurrentDomain_UnhandledException捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}", ex.GetType(), ex.Message, ex.StackTrace));
}
}
3 在方法CurrentDomain_UnhandledException入口打上断点并调试程序,弹出界面后,点击button按钮,调试结果如下:
可以看到,线程抛出异常后,就进入该事件方法了,如下图:
但叉掉提示框后,你可以发现,间大概3秒左右,程序直接退出了,所以可以猜测,当线程中如果有异常没有处理,则会导致程序崩溃退出,这样用户体验就很不好了。
好了,本文内容到此结束。
2023-06-17 日补充:
线程中未处理的异常导致程序崩溃退出的已找到解决方案,可以参考下面的博文
配置legacyUnhandledExceptionPolicy属性防止处理异常后程序崩溃退出(C#)_zxy2847225301的博客-优快云博客