0

0

C#的全局异常处理是什么?如何实现?

煙雲

煙雲

发布时间:2025-09-19 08:01:01

|

701人浏览过

|

来源于php中文网

原创

C#全局异常处理通过AppDomain和TaskScheduler事件捕获未处理异常,前者用于WinForms/WPF应用,后者处理异步任务异常,结合日志记录与用户友好提示,确保程序稳定性,且不影响正常性能。

c#的全局异常处理是什么?如何实现?

C#全局异常处理,简单来说,就是为你的程序设置一个“安全网”,当程序在运行时出现未被捕获的异常时,这个“安全网”就会启动,防止程序崩溃,并允许你记录错误信息,甚至尝试恢复。

全局异常处理的核心在于捕获那些未被try-catch块处理的异常。

解决方案

实现C#全局异常处理主要有两种方式:

  1. Application Domain级别的异常处理: 适用于桌面应用程序(WinForms, WPF)。
  2. TaskScheduler级别的异常处理: 适用于异步操作的异常处理。

1. Application Domain级别的异常处理 (WinForms/WPF)

这种方式通过监听

AppDomain.CurrentDomain.UnhandledException
事件来实现。

using System;
using System.Windows.Forms; // 或者 using System.Windows; 对于WPF

namespace GlobalExceptionHandlerExample
{
    static class Program
    {
        [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)
        {
            // 处理未处理的异常
            Exception ex = (Exception)e.ExceptionObject;

            // 记录日志
            Console.WriteLine("全局异常处理: " + ex.Message);
            // 或者使用更专业的日志库,如NLog, Serilog

            // 显示错误信息给用户 (可选)
            MessageBox.Show("程序出现未预料的错误,请查看日志文件。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

            // 决定是否终止程序
            // e.IsTerminating = true; // 默认是false,如果设置为true,程序会立即终止
        }
    }
}

重点:

  • Main
    函数中订阅
    AppDomain.CurrentDomain.UnhandledException
    事件。
  • CurrentDomain_UnhandledException
    方法是你的异常处理逻辑。
  • e.ExceptionObject
    包含了异常的详细信息。
  • e.IsTerminating
    决定了程序是否应该终止。通常情况下,不建议直接终止程序,除非你确定程序已经无法恢复。

2. TaskScheduler级别的异常处理 (异步操作)

对于异步操作,未处理的异常可能不会直接触发

AppDomain.CurrentDomain.UnhandledException
。 这时,你需要使用
TaskScheduler.UnobservedTaskException
事件。

Devin
Devin

世界上第一位AI软件工程师,可以独立完成各种开发任务。

下载
using System;
using System.Threading.Tasks;

public class Example
{
    public static void Main()
    {
        // 订阅未观察到的Task异常事件
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

        // 启动一个Task,故意抛出一个异常
        Task.Run(() => { throw new Exception("Task中发生的异常!"); });

        // 强制垃圾回收,触发UnobservedTaskException事件
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Console.ReadKey();
    }

    private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        // 处理未观察到的Task异常
        Exception ex = e.Exception.InnerException; // 获取实际的异常

        Console.WriteLine("Task异常处理: " + ex.Message);

        // 标记异常已被处理,防止程序崩溃
        e.SetObserved();
    }
}

重点:

  • TaskScheduler.UnobservedTaskException
    事件在Task的异常未被观察到(例如,未被
    await
    .Result
    访问)且Task被垃圾回收时触发。
  • e.Exception.InnerException
    包含了实际的异常。
  • 必须调用
    e.SetObserved()
    来标记异常已被处理,否则程序仍然可能崩溃。

全局异常处理会影响性能吗?

全局异常处理本身不会显著影响性能,因为它只有在发生未处理的异常时才会被触发。但是,如果在异常处理程序中执行大量的日志记录、资源清理或其他耗时操作,可能会对性能产生一定的影响。因此,建议在全局异常处理程序中尽量减少不必要的计算和I/O操作。

如何在ASP.NET Core中实现全局异常处理?

ASP.NET Core 提供了多种处理异常的方式,包括:

  • Exception Filter: 你可以创建一个全局异常过滤器来捕获和处理未处理的异常。
  • Middleware: 你可以创建一个自定义的中间件来捕获和处理异常。
  • UseExceptionHandler: ASP.NET Core 内置的中间件,可以用来处理异常并显示友好的错误页面。

使用Exception Filter的示例:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

public class GlobalExceptionFilter : IExceptionFilter
{
    private readonly ILogger _logger;

    public GlobalExceptionFilter(ILogger logger)
    {
        _logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        _logger.LogError(context.Exception, "发生全局异常");

        // 可以根据异常类型返回不同的结果
        if (context.Exception is ArgumentNullException)
        {
            context.Result = new BadRequestObjectResult("参数错误");
        }
        else
        {
            context.Result = new StatusCodeResult(500);
        }

        context.ExceptionHandled = true; // 标记异常已被处理
    }
}

需要在

Startup.cs
中注册该Filter:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.Filters.Add(typeof(GlobalExceptionFilter));
    });
}

全局异常处理的最佳实践是什么?

  • 记录详细的错误信息: 包括异常类型、消息、堆跟踪、发生时间等,以便于调试和排查问题。
  • 避免在全局异常处理程序中抛出异常: 这可能会导致无限循环或程序崩溃。
  • 不要吞噬异常: 如果无法处理异常,应该将其重新抛出,或者至少记录下来。
  • 考虑用户体验: 向用户显示友好的错误信息,而不是直接显示技术细节。
  • 使用专业的日志库: 如NLog, Serilog等,可以提供更强大的日志记录功能。
  • 区分不同类型的异常: 可以根据异常类型采取不同的处理方式,例如,对于已知类型的异常,可以进行特定的处理,对于未知类型的异常,可以进行通用的处理。
  • 在开发和测试环境中启用详细的错误报告: 这可以帮助你更快地发现和修复问题。
  • 在生产环境中禁用详细的错误报告: 避免向用户暴露敏感信息。
  • 定期审查日志文件: 分析错误趋势,找出潜在的问题。

全局异常处理并非万能的。 理想情况下,应该尽可能地在代码中处理异常,只有在无法预料的情况下才依赖全局异常处理。

相关专题

更多
什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

178

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

213

2025.12.18

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

xml格式相关教程
xml格式相关教程

本专题整合了xml格式相关教程汇总,阅读专题下面的文章了解更多详细内容。

0

2026.01.19

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

11

2026.01.19

微信聊天记录删除恢复导出教程汇总
微信聊天记录删除恢复导出教程汇总

本专题整合了微信聊天记录相关教程大全,阅读专题下面的文章了解更多详细内容。

85

2026.01.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.1万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 12.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号