Hangfire异常致ASP.NET Core应用崩溃,求跳过异常方案
Hangfire托管服务停止时抛出OperationCanceledException导致应用崩溃
异常信息
Unhandled exception. System.AggregateException: One or more hosted services failed to stop. (The operation was canceled.) ---> System.OperationCanceledException: The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException() at Hangfire.Processing.TaskExtensions.WaitOneAsync(WaitHandle waitHandle, TimeSpan timeout, CancellationToken token) at Hangfire.Processing.BackgroundDispatcher.WaitAsync(TimeSpan timeout, CancellationToken cancellationToken) at Hangfire.Server.BackgroundProcessingServer.WaitForShutdownAsync(CancellationToken cancellationToken) at Microsoft.Extensions.Hosting.Internal.Host.StopAsync(CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.Extensions.Hosting.Internal.Host.StopAsync(CancellationToken cancellationToken) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.WaitForShutdownAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at Microsoft.AspNetCore.Builder.WebApplication.Run(String url
环境版本
- ASP.NET Core 6.0.3
- Hangfire.Core 1.7.28、Hangfire.AspNetCore 1.7.28
核心代码
Startup.cs - ConfigureServices方法
services.AddHangfire(); services.AddHangfireServer();
Startup.cs - Configure方法
app.UseHangfireDashboard("/hangfire");
当前分析
异常抛出点为Microsoft.Extensions.Hosting.Internal.Host.StopAsync,Hangfire作为内部托管服务,停止时抛出OperationCanceledException,最终引发未被捕获的AggregateException,导致应用崩溃。自定义托管服务可通过IHostedService包装类捕获异常,但Hangfire的托管服务由框架自动注册,需要针对性处理方案。
解决方案
可以通过替换Hangfire托管服务的注册逻辑,用自定义包装类包裹其IHostedService实现,从而捕获停止时的异常:
- 保留你已定义的
MyHostedServiceWrapper类(可按需调整日志逻辑) - 修改
ConfigureServices中的Hangfire注册代码,手动注册并包装:
services.AddHangfire(); // 先注册Hangfire的BackgroundProcessingServer,再替换为包装后的服务 services.AddSingleton<BackgroundProcessingServer>(); services.AddSingleton<IHostedService>(sp => new MyHostedServiceWrapper( sp.GetRequiredService<ILogger<MyHostedServiceWrapper>>(), sp.GetRequiredService<BackgroundProcessingServer>()));
如果需要保留Hangfire的默认配置选项,可调整为:
services.AddHangfire(); // 先添加HangfireServer的自定义配置 services.AddHangfireServer(options => { // 此处添加你的HangfireServer配置项 }); // 移除默认注册的IHostedService,替换为包装后的版本 var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IHostedService) && d.ImplementationType == typeof(BackgroundProcessingServer)); if (descriptor != null) { services.Remove(descriptor); services.AddSingleton<IHostedService>(sp => new MyHostedServiceWrapper( sp.GetRequiredService<ILogger<MyHostedServiceWrapper>>(), ActivatorUtilities.CreateInstance<BackgroundProcessingServer>(sp, descriptor.ImplementationInstance))); }
通过此方式,Hangfire服务停止时抛出的异常会被包装类捕获并记录日志,不会向上传递导致应用崩溃。另外,也可以尝试升级Hangfire到最新稳定版本,新版本可能已修复停止阶段抛出取消异常的问题。
内容的提问来源于stack exchange,提问作者Arvind Maurya
相关产品推荐
相关产品推荐

