dotnet未捕获异常导致系统崩溃问题

一般情况下我们业务代码不需要自己捕获异常,因为目前我们常用框架都会自行处理异常,但是有些情况下需要自己处理异常,否则未处理的异常抛出会导致程序崩溃退出。

1.全局异常捕获

// 1. AppDomain 未处理异常
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
    var exception = e.ExceptionObject as Exception;
    LogException(exception, "UnhandledException");
    
    if (e.IsTerminating)
    {
        // 进程即将终止
        EmergencyShutdown();
    }
};

// 2. Task 未观察异常 (.NET 4.0+)
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
    LogException(e.Exception, "UnobservedTaskException");
    e.SetObserved(); // 防止进程崩溃
};

// 3. Windows Forms
if (Application.MessageLoop)
{
    Application.ThreadException += (sender, e) =>
    {
        LogException(e.ception, "ThreadException");
    };
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
}

// 4. WPF
Dispatcher.CurrentDispatcher.UnhandledException += (sender, e) =>
{
    LogException(e.Exception, "DispatcherUnhandledException");
    e.Handled = true; // 阻止进程崩溃
};

// 5. ASP.NET Core
// 在 Program.cs 中使用 UseExceptionHandler 中间件

2.Timer异常 和 异步void方法异常

定时器的事件方法中的代码抛出来的异常,无法被全局异常捕获,同样异步void方法异常也是的,需要自行捕获异常。

public class SafeTimer
{
    private readonly Timer _timer;
    
    public SafeTimer()
    {
        _timer = new Timer(OnTimerCallback);
    }
    
    private void OnTimerCallback(object state)
    {
        try
        {
            // 业务逻辑
        }
        catch (Exception ex)
        {
            // 记录日志,通知主线程
            LogException(ex);
        }
    }
}

3.StackOverflowException和OutOfMemoryException

这两个异常业务无法捕获的,因为它们发生时,程序以及没有办法在执行如何代码了,只能靠上个文章中说的崩溃自动收集dump,然后去分析dump找出问题。
还有其他比如调用c代码等不安全代码,大部分时候也时无法捕获,如果它们引起异常也很难捕获。

posted @ 2025-12-18 21:29  Rick Carter  阅读(26)  评论(1)    收藏  举报