.NET 6控制台应用中Quartz.NET任务无法触发求助
.NET 6控制台Quartz.NET任务无法执行的问题排查与修复
核心问题1:调度器被立即终止
你的ScheduleQuartzNet方法中,刚完成任务调度就立刻调用await scheduler.Shutdown();,这会直接关掉Quartz调度器进程,任务根本没机会触发执行。
修复方式:
删掉await scheduler.Shutdown();,把调度器实例存为类成员,等应用退出时再关闭:
修改后的调度器代码:
private IScheduler _scheduler; // 保存调度器实例 public async Task ScheduleQuartzNet() { _scheduler = await StdSchedulerFactory.GetDefaultScheduler(); await _scheduler.Start(); IJobDetail job = JobBuilder.Create<BackGroundJob>().Build(); ITrigger trigger = TriggerBuilder.Create() .WithDailyTimeIntervalSchedule(schd => { schd.WithIntervalInSeconds(20); schd.OnEveryDay(); schd.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(21,59)); }) .Build(); try { await _scheduler.ScheduleJob(job, trigger); // 移除立即关闭调度器的代码 } catch (Exception ex) { Console.WriteLine(ex.Message); } } // 应用退出时调用此方法关闭调度器 public async Task ShutdownScheduler() { if (_scheduler != null && !_scheduler.IsShutdown) { await _scheduler.Shutdown(); } }
核心问题2:Job的依赖注入未配置
BackGroundJob的构造函数依赖WorkerClass,但Quartz默认的SimpleJobFactory不支持构造函数注入,会导致创建Job实例时抛出异常——就算调度器正常运行,任务也执行不了。
修复方式:
推荐用Quartz官方的DI扩展包,步骤如下:
- 安装NuGet包:
Quartz.Extensions.DependencyInjection - 在Program.cs里配置Quartz服务:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { // 注册Quartz服务 services.AddQuartz(q => { q.AddJob<BackGroundJob>(j => j.WithIdentity("BackGroundJob")); q.AddTrigger(t => t .ForJob("BackGroundJob") .WithDailyTimeIntervalSchedule(s => { s.WithIntervalInSeconds(20); s.OnEveryDay(); s.StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(21,59)); }) .WithIdentity("BackGroundJobTrigger")); }); // 启动Quartz宿主服务,确保任务执行完成后再退出 services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true); // 把WorkerClass注册到DI容器 services.AddScoped<WorkerClass>(); }) .Build(); await host.RunAsync();
额外问题:触发器配置可能不符合预期
你用WithDailyTimeIntervalSchedule并指定StartingDailyAt(21,59),意味着触发器只会在每天21:59之后才开始每隔20秒执行一次。如果当前时间早于21:59,任务要等到当天21:59才会首次触发。
如果需求是立即开始每隔20秒执行,换成SimpleTrigger:
ITrigger trigger = TriggerBuilder.Create() .WithSimpleSchedule(s => s .WithIntervalInSeconds(20) .RepeatForever()) .Build();
调用代码调整
原调用代码里,await qs.ScheduleQuartzNet();后虽然有Console.ReadLine(),但之前调度器被提前关闭,根本没用。修改后要确保应用保持运行,等用户操作后再关闭调度器:
using BackgroundJob; QuartzNetScheduler qs = new QuartzNetScheduler(); await qs.ScheduleQuartzNet(); Console.WriteLine("按任意键退出..."); Console.ReadKey(); // 退出前关闭调度器 await qs.ShutdownScheduler();
内容的提问来源于stack exchange,提问作者So_oP
相关产品推荐
相关产品推荐

