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

Quartz.NET自定义Job配置DI能力注册及DI异常解决

问题解决方案

1. 过时的UseMicrosoftDependencyInjectionJobFactory替代方案

新版Quartz中,UseMicrosoftDependencyInjectionJobFactory已被废弃,替代方案是使用UseMicrosoftDependencyInjectionScopedJobFactory,它支持更合理的作用域管理,确保Job执行时能正确获取作用域服务。修改后的注册代码如下:

public static class QuartzExtensions {
    public static IServiceCollection AddQuartzSetup(this IServiceCollection services) {
        services.AddQuartz(opts => {
            // 替代过时方法,启用依赖注入作用域Job工厂
            opts.UseMicrosoftDependencyInjectionScopedJobFactory();
        });
        services.AddQuartzHostedService(options => { options.WaitForJobsToComplete = true; });
        // 注册异步配置类
        services.AddTransient<IAsyncConfigureOptions<QuartzOptions>, UpdateS3BackgroundJobSetup>();

        return services;
    }
}

如果使用较新版本的Quartz.AspNetCore,AddQuartz默认已集成DI Job工厂支持,也可省略显式调用UseMicrosoftDependencyInjectionScopedJobFactory,但显式声明会更清晰。

2. 解决单例IOptions<QuartzOptions>消费作用域服务的DI异常

问题根源

IConfigureOptions<QuartzOptions>实例是单例生命周期,而IApplicationConfigurationDbContext是作用域生命周期,根据.NET DI规则,单例服务不能直接依赖作用域服务,否则会导致作用域服务被单例持有,引发生命周期不匹配异常。

解决方法

改用IAsyncConfigureOptions<QuartzOptions>异步配置接口,通过IServiceScopeFactory手动创建作用域获取DbContext,避免直接注入作用域服务到单例中。修改配置类如下:

public class UpdateS3BackgroundJobSetup : IAsyncConfigureOptions<QuartzOptions> {
    private readonly IServiceScopeFactory _scopeFactory;

    public UpdateS3BackgroundJobSetup(IServiceScopeFactory scopeFactory) {
        _scopeFactory = scopeFactory;
    }

    public async Task ConfigureAsync(QuartzOptions options, CancellationToken cancellationToken) {
        // 创建临时作用域,获取DbContext
        using var scope = _scopeFactory.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService<IApplicationConfigurationDbContext>();

        var configuration = await dbContext.ApplicationConfigurations
            .Where(cfg => cfg.Name == "metamorph-db")
            .FirstOrDefaultAsync(cancellationToken);

        var jobKey = JobKey.Create(nameof(OutgoingRegistriesJob));

        options
            .AddJob<OutgoingRegistriesJob>(jobBuilder => jobBuilder.WithIdentity(jobKey))
            .AddTrigger(trigger =>
                trigger
                    .ForJob(jobKey)
                    .WithSimpleSchedule(schedule =>
                        schedule.WithIntervalInMinutes(5).RepeatForever()));
    }
}

额外注意事项

  • 替换原注册方式:将services.ConfigureOptions<UpdateS3BackgroundJobSetup>()改为services.AddTransient<IAsyncConfigureOptions<QuartzOptions>, UpdateS3BackgroundJobSetup>(),适配异步配置接口。
  • 移除async void:原代码中Configure方法使用async void会导致异步操作无法被正确追踪,改用IAsyncConfigureOptions的ConfigureAsync方法(返回Task),确保异步操作可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:41:39