WinForm 全局异常捕获

本文介绍了在程序开发中如何实现全局异常捕获,包括UI线程和非UI线程的未处理异常处理,以避免程序因未预期异常而崩溃,提升用户体验。通过设置Application DispatcherUnhandledException和AppDomain UnhandledException事件,可以有效地捕获并显示异常信息,同时提供了异常信息提取的辅助方法。
摘要由CSDN通过智能技术生成

在开发过程中我们一般都用try/catch块来捕获异常,但不是每个异常我们都能捕获,程序总会出现一些意想不到的情况,抛出一些未捕获的异常,这时就要用到全局异常捕获,即在程序的最外层加上捕获未处理异常,以免程序奔溃,影响用户体验。

事件描述
Application.DispatcherUnhandledExceptionUI线程的未处理异常捕获
AppDomain.UnhandledException非UI线程的未处理异常捕获
  • 构造中添加注册事件
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
    try
    {
        //设置应用程序处理异常方式:ThreadException处理
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        //UI线程的未处理异常捕获
        Application.ThreadException += Application_ThreadException;
        //非UI线程的未处理异常捕获
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
    catch (Exception ex)
    {
        string str = ExceptionToString(ex, "主线程");
        MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
  • 提取异常信息函数
/// <summary>
/// 提取异常信息
/// </summary>
private static string ExceptionToString(Exception ex, string info)
{
    StringBuilder str = new StringBuilder($"{DateTime.Now}, {info}发生了一个错误!{Environment.NewLine}");
    if (ex.InnerException == null)
    {
        str.Append($"【对象名称】:{ex.Source}{Environment.NewLine}");
        str.Append($"【异常类型】:{ex.GetType().Name}{Environment.NewLine}");
        str.Append($"【详细信息】:{ex.Message}{Environment.NewLine}");
        str.Append($"【堆栈调用】:{ex.StackTrace}");
    }
    else
    {
        str.Append($"【对象名称】:{ex.InnerException.Source}{Environment.NewLine}");
        str.Append($"【异常类型】:{ex.InnerException.GetType().Name}{Environment.NewLine}");
        str.Append($"【详细信息】:{ex.InnerException.Message}{Environment.NewLine}");
        str.Append($"【堆栈调用】:{ex.InnerException.StackTrace}");
    }
    return str.ToString();
}
  • UI线程未捕获异常处理函数
/// <summary>
/// UI线程未捕获异常处理函数
/// </summary>
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    try
    {
        string msg = ExceptionToString(e.Exception, "UI线程");
        MessageBox.Show(msg, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
        string msg = ExceptionToString(ex, "UI线程 处理函数");
        MessageBox.Show(msg, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
  • 非UI子线程未捕获异常处理函数
/// <summary>
/// 非UI线程未捕获异常处理函数
/// </summary>
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    try
    {
        string msg;
        if (e.ExceptionObject is Exception ex)
        {
            msg = ExceptionToString(ex, "非UI线程");
        }
        else
        {
            msg = $"发生了一个错误!信息:{e.ExceptionObject}";
        }
        MessageBox.Show(msg, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
        string msg = ExceptionToString(ex, "非UI线程 处理函数");
        MessageBox.Show(msg, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

备注:子线程异常处理完成后程序还是会结束,如果不希望程序退出则在App.config中添加如下内容

<configuration>
    <runtime>
	    <legacyUnhandledExceptionPolicy enabled="1"/>
	</runtime>
</configuration>

这里的 <legacyUnhandledExceptionPolicy enabled=“1”/>,用意是使用早期版本的异常处理策略。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

share notes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>