Quartz.Net定时任务仅执行一次问题及并发执行规避咨询
问题解决:Quartz.NET任务仅执行一次&避免Job并发执行
我来帮你一步步解决这两个问题:
一、任务仅执行一次的原因及修复
你当前的代码里,SimpleSchedule只设置了执行间隔,但Quartz的SimpleScheduleBuilder默认只执行一次(重复次数为0),这才是任务只跑一次的核心原因——StoreDurably(true)是用来让Job在没有触发器关联时依然保留在调度器中,和重复执行完全无关。
修复方法很简单,在WithSimpleSchedule的配置里加上.RepeatForever()(永久重复),或者用.WithRepeatCount(n)指定固定重复次数:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity($"trigger_RinnovoJob", "sender") .StartNow() .WithSimpleSchedule(x => x.WithInterval(interval) .RepeatForever() // 关键:添加永久重复配置 ) .Build();
另外,如果你习惯用Cron表达式,也可以改用CronSchedule来实现每30分钟执行,可读性更强:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity($"trigger_RinnovoJob", "sender") .StartNow() .WithCronSchedule("0 */30 * ? * *") // 每30分钟执行一次的Cron表达式 .Build();
二、避免同类型Job并发执行
有两种常用方案可以实现这个需求:
1. 使用DisallowConcurrentExecution特性
直接在你的RinnovoJob类上添加这个特性,Quartz会自动确保同一个JobDetail的实例不会同时执行——如果前一次任务还在运行,下一次到点的任务会等待前一次完成后再执行:
[DisallowConcurrentExecution] public class RinnovoJob:IJob { // 你的Job实现代码 }
2. 配置触发器的Misfire处理策略
如果你的任务可能因为某些原因错过执行时间(比如服务重启、前一次执行超时),可以结合触发器的Misfire处理策略来增强控制。比如在SimpleSchedule中添加:
.WithSimpleSchedule(x => x.WithInterval(interval) .RepeatForever() .WithMisfireHandlingInstructionIgnoreMisfires() // 忽略错过的执行,等待下一次正常触发 )
这个配置会让Quartz跳过所有错过的执行,直接等待下一个预定的执行时间,避免堆积任务。
额外注意点
还要确保你的调度器scheduler的生命周期是正确的:比如在ASP.NET Core中,要把Core类注册为单例服务,并且确保宿主启动后不会立即关闭,否则调度器会被终止,任务也就不会继续执行了。
内容的提问来源于stack exchange,提问作者advapi
相关产品推荐
相关产品推荐

