C# 中如何记录未捕获的异常?

C# 记录未捕获异常:订阅 AppDomain.UnhandledException 事件记录全局异常,TaskScheduler.UnobservedTaskException 处理异步任务异常。本文给出完整实现。

最佳实践
C# 中如何记录未捕获的异常?封面

核心:在程序入口订阅 AppDomain.CurrentDomain.UnhandledException 事件,在回调中用日志框架(如 NLog/log4net)记录异常详情,确保进程崩溃前留下完整的错误信息。

完整实现

using System;
using NLog;

class Program
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    static void Main(string[] args)
    {
        // 订阅全局未捕获异常事件
        AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
        {
            var ex = e.ExceptionObject as Exception;
            Logger.Fatal(ex, "未捕获的异常导致程序崩溃");
        };

        // 捕获异步任务中未观察到的异常
        TaskScheduler.UnobservedTaskException += (sender, e) =>
        {
            Logger.Error(e.Exception, "异步任务中出现未处理的异常");
            e.SetObserved();  // 标记为已处理,防止进程崩溃
        };

        // 正常业务逻辑...
    }
}

ASP.NET Core 的方式

// Program.cs / Startup.cs
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var feature = context.Features.Get<IExceptionHandlerFeature>();
        logger.LogError(feature?.Error, "未处理的请求异常");
        await context.Response.WriteAsync("服务器内部错误");
    });
});

观测云对照

观测云 APM 通过探针自动捕获 .NET 应用中的未处理异常,包含完整的堆栈、请求上下文和调用链路,不需要手动订阅事件;异常信息在观测云控制台中聚合展示和告警。

常见问题(FAQ)

Q:.NET Core / .NET 5+ 还需要 AppDomain 事件吗?
A:仍然有效,但 ASP.NET Core 更推荐用中间件(ExceptionHandlerMiddleware)统一处理请求管道中的异常。

Q:async/await 中的异常能被 UnhandledException 捕获吗?
A:不能。异步 Task 中的异常由 TaskScheduler.UnobservedTaskException 处理,两者都需要订阅。

Q:记录完异常后程序会继续运行吗?
A:UnhandledException 触发时进程已经在终止过程中,你只能记录日志、不能做恢复操作。UnobservedTaskException 调用 SetObserved() 后可以阻止进程崩溃。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台