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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:24:03