You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 2.1中如何全局捕获异常避免程序崩溃?

.NET Core 2.1 后台服务全局异常捕获方案

针对你遇到的后台服务未处理异常导致程序崩溃的问题,以下是可行的解决方法:

1. 在后台服务执行逻辑中直接捕获异常

.NET Core 2.1 中BackgroundService(IHostedService的抽象实现)的核心执行逻辑在ExecuteAsync方法里,直接在这个方法内包裹全局try-catch,就能捕获业务逻辑抛出的异常,阻止其冒泡到主机进程导致崩溃:

public class MyBackgroundService : BackgroundService
{
    private readonly ILogger<MyBackgroundService> _logger;

    public MyBackgroundService(ILogger<MyBackgroundService> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // 替换为你的后台业务逻辑
                await RunBusinessLogic(stoppingToken);
            }
            catch (Exception ex)
            {
                // 记录异常日志
                _logger.LogError(ex, "后台服务执行发生未处理异常");
                // 可选:异常后延迟重试,避免频繁报错
                await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken);
            }
        }
    }

    private async Task RunBusinessLogic(CancellationToken stoppingToken)
    {
        // 你的业务代码
    }
}

这种方式最直接,适合单个或少量后台服务的场景。

2. 自定义统一异常包装器,批量处理所有后台服务

如果有多个后台服务,不想逐个修改,可以实现一个IHostedService的包装类,统一处理所有被包裹服务的启动、执行、停止阶段的异常:

public class HostedServiceExceptionWrapper : IHostedService
{
    private readonly IHostedService _innerService;
    private readonly ILogger<HostedServiceExceptionWrapper> _logger;
    private Task _executingTask;
    private CancellationTokenSource _stoppingCts;

    public HostedServiceExceptionWrapper(IHostedService innerService, ILogger<HostedServiceExceptionWrapper> logger)
    {
        _innerService = innerService;
        _logger = logger;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        _stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
        try
        {
            // 启动内部服务
            await _innerService.StartAsync(_stoppingCts.Token);
            // 如果是BackgroundService,单独处理ExecuteAsync的异常
            if (_innerService is BackgroundService backgroundService)
            {
                _executingTask = ExecuteWithExceptionHandling(backgroundService, _stoppingCts.Token);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "后台服务启动失败");
        }
    }

    private async Task ExecuteWithExceptionHandling(BackgroundService service, CancellationToken stoppingToken)
    {
        try
        {
            await service.ExecuteAsync(stoppingToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "后台服务执行过程中发生未处理异常");
            // 可选:可以在这里尝试重启服务,或者做其他恢复操作
        }
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        try
        {
            _stoppingCts?.Cancel();
            if (_executingTask != null)
            {
                await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
            }
            await _innerService.StopAsync(cancellationToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "后台服务停止失败");
        }
        finally
        {
            _stoppingCts?.Dispose();
        }
    }
}

注册服务时用这个包装器包裹你的实际后台服务:

services.AddTransient<MyBackgroundService>();
services.AddHostedService<HostedServiceExceptionWrapper>(provider =>
    new HostedServiceExceptionWrapper(
        provider.GetRequiredService<MyBackgroundService>(),
        provider.GetRequiredService<ILogger<HostedServiceExceptionWrapper>>()));

关于AppDomain.CurrentDomain.FirstChanceException的说明

这个事件只是在异常第一次被抛出时触发通知,它不会阻止异常的传播,所以即便捕获到事件,异常依然会继续向上冒泡,最终导致程序崩溃。它的主要作用是调试时追踪所有异常的抛出点,或者记录所有异常信息,但无法解决崩溃问题。

内容的提问来源于stack exchange,提问作者Ivan Law

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:32:38