MVC中Quartz作业构造函数依赖注入及按钮点击启停调度器问题
Quartz 点击按钮启动带依赖注入作业的修复方案
核心问题原因
现有代码的核心问题出在依赖注入的服务注册逻辑上:
- 仅将
Program类注册为IProgram接口的单例实现,但自定义的MyJobFactory尝试解析的是Program类本身的类型,容器中没有对应注册,所以无法实例化带参构造的作业 Program作为作业类不应该注册为单例,Quartz 每次执行作业都需要全新的实例,避免线程安全问题- 缺少重复调度防护,多次点击按钮会重复添加相同的作业和触发器,抛出调度异常
具体修改步骤
1. 修改 Startup.cs 服务注册
public void ConfigureServices(IServiceCollection services) { services.AddTransient<IDataBaseService, DB2Service>(); services.AddTransient<IJobFactory, MyJobFactory>(); services.AddSingleton<IMyScheduler, MyScheduler>(); // 移除原来的services.AddSingleton<IProgram, Program>(); // 注册Program类本身,生命周期设为瞬时,适配Quartz作业要求 services.AddTransient<Program>(); services.AddControllersWithViews(); }
2. 优化 MyJobFactory 解析逻辑
将GetService改为GetRequiredService,解析失败时抛出明确的异常,方便问题排查:
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { try { // 改为GetRequiredService避免空引用异常 return (IJob)this._provider.GetRequiredService(bundle.JobDetail.JobType); } catch (Exception e) { throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the ASPnet Core IOC", bundle.JobDetail.Key), e); } }
3. 优化 MyScheduler 调度逻辑,添加重复调度防护
public async Task Run_A_Scheduler() { // 先判断调度器是否已经启动、作业是否已经存在,避免重复添加 if (scheduler.IsStarted && await scheduler.CheckExists(new JobKey(nameof(Program)))) { return; } this.job = CreateJob<Program>(); this.trigger = TriggerBuilder.Create() .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(20) .RepeatForever()) .Build(); await this.scheduler.ScheduleJob(job, this.trigger); await this.scheduler.Start(); }
4. 清理控制器无用注入(可选)
控制器中注入的IProgram没有实际作用,可以直接移除,简化代码:
public class SiteController : Controller { private readonly IMyScheduler _MyScheduler; private readonly IDataBaseService _DataBaseService; public SiteController(IMyScheduler MyScheduler, IDataBaseService DataBaseService) { _MyScheduler = MyScheduler; _DataBaseService = DataBaseService; } public async Task<ActionResult> ButtonClick() { await _MyScheduler.Run_A_Scheduler(); return Ok(); } }
以上修改完成后,点击按钮启动调度时,Quartz 会通过自定义的 JobFactory 从容器中解析带依赖的Program实例,正常执行作业逻辑。
内容的提问来源于stack exchange,提问作者krzysiek272
相关产品推荐
相关产品推荐

