Hangfire注入Scoped服务执行后台作业时的异常问题
问题解决方案
错误原因分析
第一个异常(变量未定义)
初始代码中,Enqueue<MyStorageService>(s => EnqueueJob(s)) 的写法存在逻辑问题:Hangfire 无法正确解析嵌套调用静态方法的表达式,s 作为参数的作用域无法被识别,导致表达式编译失败。另外,async void 类型的作业方法会导致 Hangfire 无法跟踪任务状态,也无法正确处理异常。
第二个异常(空引用)
你在控制器中提前创建作用域并获取 MyStorageService 实例,再将实例传递给 Hangfire 作业。但 Hangfire 会序列化作业参数,而Scoped 服务(如依赖的 EF Core DbContext)无法被正确序列化,当作业执行时,实例已脱离原作用域,内部依赖(如 DbContext)已失效或未被初始化,从而引发空引用异常。
正确实现方案
Hangfire 原生支持依赖注入,应让 Hangfire 在执行作业时自动创建作用域并解析 Scoped 服务,而非提前在控制器中实例化服务。
步骤1:创建独立的作业服务类
将作业逻辑封装到单独的类中,避免与控制器耦合,同时便于 Hangfire 解析依赖:
public class MyJobExecutor { private readonly MyStorageService _storageService; // 通过构造函数注入Scoped服务 public MyJobExecutor(MyStorageService storageService) { _storageService = storageService; } [JobDisplayName("My job"), DisableConcurrentExecution(10 * 60)] public async Task RunJobAsync() { await _storageService.DoAsync(); } }
步骤2:注册作业服务
在 Program.cs 中将作业服务注册为 Scoped(与 MyStorageService 生命周期一致):
builder.Services.AddScoped<MyJobExecutor>();
步骤3:修改控制器Action
在控制器中直接让 Hangfire 调度作业服务的方法,Hangfire 会自动处理依赖注入和作用域创建:
private readonly IBackgroundJobClient _backgroundJobClient; // 控制器构造函数注入IBackgroundJobClient public MyController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = backgroundJobClient; } [HttpPost] public string DoSomething() { // 让Hangfire自动解析MyJobExecutor并执行作业 var jobId = _backgroundJobClient.Enqueue<MyJobExecutor>(executor => executor.RunJobAsync()); return jobId; }
步骤4:确保Hangfire配置正确
在 Program.cs 配置 Hangfire 时,确保使用应用的服务提供器:
builder.Services.AddHangfire(config => { // 配置Hangfire存储(如SQL Server、Redis等) config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection")); // 关联应用的服务提供器,支持依赖注入 config.UseServiceProviderFactory(new DefaultServiceProviderFactory()); }); builder.Services.AddHangfireServer();
关键注意事项
- 作业方法必须返回
async Task,禁止使用async void,否则 Hangfire 无法跟踪任务完成状态和处理异常。 - Scoped 服务(如
MyStorageService、EF Core DbContext)只能由 Hangfire 在作业执行时解析,不能提前实例化后传递给作业。 - Hangfire 会为每个作业创建独立的作用域,作业执行完成后自动释放作用域内的所有服务,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

