Quartz.NET异步定时任务仅首次执行问题求助
解决Quartz定时任务仅首次执行的问题
我来帮你排查下这个Quartz定时任务只跑一次的问题,常见的原因和解决办法如下:
1. Scheduler实例被GC回收
你在Application_Start里用GetAwaiter().GetResult()同步等待Start()方法,但如果IScheduler只是Start()方法里的局部变量,方法执行完毕后它很可能被垃圾回收机制回收,导致后续任务无法触发。
解决办法:把IScheduler作为JobScheduler的静态成员变量保存,确保它始终被引用:
public static class JobScheduler { // 静态成员保存Scheduler,防止被GC回收 private static IScheduler _scheduler; public static async Task Start() { try { NameValueCollection props = new NameValueCollection { { "quartz.serializer.type", "binary" } }; StdSchedulerFactory factory = new StdSchedulerFactory(props); _scheduler = await factory.GetScheduler(); await _scheduler.Start(); // 配置你的Job和每10分钟执行的Trigger IJobDetail job = JobBuilder.Create<YourAsyncJob>() .WithIdentity("asyncJob", "jobGroup") .Build(); ITrigger trigger = TriggerBuilder.Create() .WithIdentity("10MinTrigger", "triggerGroup") .StartNow() .WithSimpleSchedule(schedule => schedule .WithIntervalInMinutes(10) .RepeatForever()) // 关键:确保是永久重复,不是只执行一次 .Build(); await _scheduler.ScheduleJob(job, trigger); } catch (SchedulerException ex) { // 务必添加日志,方便排查异常 Console.WriteLine($"Scheduler启动失败:{ex.Message}"); } } }
2. 异步Job的执行逻辑有误
如果你的异步Job没有正确处理异步操作,比如没加await或者阻塞了线程,可能导致Quartz误判任务状态,甚至引发未捕获异常终止后续触发。
正确的异步Job写法:
public class YourAsyncJob : IJob { public async Task Execute(IJobExecutionContext context) { try { // 确保所有异步操作都用await等待完成 await RunYourAsyncTask(); } catch (Exception ex) { // 捕获异常避免影响Quartz调度器 Console.WriteLine($"Job执行失败:{ex.Message}"); } } private async Task RunYourAsyncTask() { // 你的业务异步逻辑,比如调用API、数据库操作等 } }
3. 检查Trigger的配置是否正确
很容易犯的错误是不小心设置了只执行一次的Trigger,比如用了WithRepeatCount(0)而不是RepeatForever()。一定要确认你的Trigger配置是永久重复的,并且时间间隔设置正确。
4. IIS应用程序池回收的影响
如果你的应用部署在IIS上,默认的应用程序池回收机制会定期重启应用,导致Quartz调度器被销毁。
解决办法:
- 调整IIS应用程序池的回收设置,比如延长回收时间、禁用闲置超时等。
- 配置Quartz的持久化存储(比如使用SQL Server、MySQL等数据库),这样应用重启后,调度器可以从持久化存储中恢复任务状态,继续执行后续任务。
内容的提问来源于stack exchange,提问作者Tiago
相关产品推荐
相关产品推荐

