Quartz.Net间隔N周/日/年定时触发器写法总结

Posted OMI天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz.Net间隔N周/日/年定时触发器写法总结相关的知识,希望对你有一定的参考价值。

由于近日在定时器中对特殊的规则(既不能通过表达式直接体现的)的用法初步汇总:

本次使用的Quartz.Net的版本号:2.6

1.触发器测试验证

  public class TestQuartz
    
        /// <summary>
        /// 间隔N周定时触发器写法测试
        /// </summary>
        public static void TestWeeklyIntervalGetFireTimeAfter()
        
            DateTimeOffset startCalendar = DateBuilder.DateOf(1, 10, 0, 1, 1, 2023);

            var yearlyTrigger = new CalendarIntervalTriggerImpl
            
                StartTimeUtc = startCalendar,
                RepeatIntervalUnit = IntervalUnit.Week,
                RepeatInterval = 2,
                PreserveHourOfDayAcrossDaylightSavings = true
            ;

            DateTimeOffset targetCalendar = startCalendar.AddDays(7 * 2); // jump 24 weeks (4 intervals)

            IList<DateTimeOffset> fireTimes = TriggerUtils.ComputeFireTimes(yearlyTrigger, null, 24);
            DateTimeOffset fifthTime = fireTimes[1]; // get the fifth fire time

            Assert.AreEqual(targetCalendar, fifthTime, "Week increment result not as expected.");
        
        /// <summary>
        /// 间隔N天定时触发器写法测试
        /// </summary>
        public static void TestDayIntervalGetFireTimeAfter()
        
            DateTimeOffset startCalendar = DateBuilder.DateOf(1, 10, 0, 1, 1, 2023);

            var yearlyTrigger = new CalendarIntervalTriggerImpl
            
                StartTimeUtc = startCalendar,
                RepeatIntervalUnit = IntervalUnit.Day,
                RepeatInterval = 1,
                PreserveHourOfDayAcrossDaylightSavings = true
            ;

            DateTimeOffset targetCalendar = startCalendar.AddDays(1); // jump 24 weeks (4 intervals)

            IList<DateTimeOffset> fireTimes = TriggerUtils.ComputeFireTimes(yearlyTrigger, null, 365);
            DateTimeOffset fifthTime = fireTimes[1]; // get the fifth fire time

            Assert.AreEqual(targetCalendar, fifthTime, "Week increment result not as expected.");
        
        /// <summary>
        /// 间隔N月定时触发器写法测试
        /// </summary>
        public static void TestMonthIntervalGetFireTimeAfter()
        
            DateTimeOffset startCalendar = DateBuilder.DateOf(23, 20, 0, 1, 1, 2023);

            var yearlyTrigger = new CalendarIntervalTriggerImpl
            
                StartTimeUtc = startCalendar,
                RepeatIntervalUnit = IntervalUnit.Month,
                RepeatInterval = 1,
                PreserveHourOfDayAcrossDaylightSavings = true
            ;

            DateTimeOffset targetCalendar = startCalendar.AddMonths(1); // jump 24 weeks (4 intervals)

            IList<DateTimeOffset> fireTimes = TriggerUtils.ComputeFireTimes(yearlyTrigger, null, 12);
            DateTimeOffset fifthTime = fireTimes[1]; // get the fifth fire time

            Assert.AreEqual(targetCalendar, fifthTime, "Week increment result not as expected.");
        
    

注册工具实现

    /// <summary>
    /// 定时器管理工具类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class QuartzManager<T> where T : class, IJob
    
        #region 变量
        /// <summary>
        /// scheduler工厂
        /// </summary>
        private static ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
        /// <summary>
        /// Job群组名
        /// </summary>
        private static String JOB_GROUP_NAME = "JOBGROUP_NAME";
        /// <summary>
        /// 触发器群组名
        /// </summary>
        private static String TRIGGER_GROUP_NAME = "TRIGGERGROUP_NAME";
        private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion

        #region 添加,删除,修改Job方法
        /// <summary>
        /// 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="pStrCronExpress">触发器表达式</param>
        public static void addJob(string pStrJobName, string pStrCronExpress, IDictionary<string, object> pDictionary)
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                // 创建任务
                IJobDetail job = JobBuilder.Create<T>()
                    .WithIdentity(pStrJobName, JOB_GROUP_NAME)
                    .Build();

                // 创建触发器
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity(pStrJobName, TRIGGER_GROUP_NAME)
                    .WithCronSchedule(pStrCronExpress)
                    .Build();

                //给任务传参数
                foreach (KeyValuePair<string, object> kvp in pDictionary)
                
                    job.JobDataMap.Put(kvp.Key, kvp.Value);
                

                sched.ScheduleJob(job, trigger);
                logger.Info("加载了服务:" + pStrJobName);
            
            catch (Exception e)
            
                logger.Info("加载异常:" + e.Message);
                throw new Exception(e.Message);
            
        

        /// <summary>
        /// 添加一个定时任务,使用自定义规则
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="doDailyTime">自定义执行情况</param>
        /// <param name="doCalendar">自定义执行情况</param>
        /// <param name="startTimeUtc">触发器执行起点时间</param>
        public static void addJob(string pStrJobName, Action<DailyTimeIntervalScheduleBuilder> doDailyTime
            , Action<CalendarIntervalScheduleBuilder> doCalendar,
          DateTimeOffset startTimeUtc,
            IDictionary<string, object> pDictionary)
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                // 创建任务
                IJobDetail job = JobBuilder.Create<T>()
                    .WithIdentity(pStrJobName, JOB_GROUP_NAME)
                    .Build();

                // 创建触发器
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity(pStrJobName, TRIGGER_GROUP_NAME)
                    .WithCalendarIntervalSchedule(d =>
                    
                        if (doCalendar != null)
                         doCalendar(d); 
                    )
                    .WithDailyTimeIntervalSchedule(d =>
                    
                        if (doCalendar != null)
                         doDailyTime(d); 
                    )
                    .StartAt(startTimeUtc)
                    .Build();

                //给任务传参数
                foreach (KeyValuePair<string, object> kvp in pDictionary)
                
                    job.JobDataMap.Put(kvp.Key, kvp.Value);
                

                sched.ScheduleJob(job, trigger);
                logger.Info("加载了服务:" + pStrJobName);
            
            catch (Exception e)
            
                logger.Info("加载异常:" + e.Message);
                throw new Exception(e.Message);
            
        

        /// <summary>
        /// 定时器高级注册应用
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="myTrigger">自定义</param>
        /// <param name="pDictionary">自定义参数</param>
        public static void addJob<TiggerImpl>(string pStrJobName, Func<TiggerImpl, ITrigger> myTrigger,
            IDictionary<string, object> pDictionary)
            where TiggerImpl : CalendarIntervalTriggerImpl
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                // 创建任务
                IJobDetail job = JobBuilder.Create<T>()
                    .WithIdentity(pStrJobName, JOB_GROUP_NAME)
                    .Build();

                // 创建触发器
                ITrigger trigger = myTrigger(Activator.CreateInstance<TiggerImpl>());

                //给任务传参数
                foreach (KeyValuePair<string, object> kvp in pDictionary)
                
                    job.JobDataMap.Put(kvp.Key, kvp.Value);
                

                sched.ScheduleJob(job, trigger);
                logger.Info("加载了服务:" + pStrJobName);
            
            catch (Exception e)
            
                logger.Info("加载异常:" + e.Message);
                throw new Exception(e.Message);
            
        



        /// <summary>
        /// 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
        /// </summary>
        /// <param name="pStrJobName">任务名称</param>
        public static void RemoveJob(string pStrJobName)
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                JobKey jobKey = new JobKey(pStrJobName);
                TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
                sched.PauseTrigger(triggerKey);// 停止触发器
                sched.UnscheduleJob(triggerKey);// 移除触发器
                sched.DeleteJob(jobKey);// 删除任务
                logger.Info("卸载了服务:" + pStrJobName);
            
            catch (Exception e)
            
                logger.Info("卸载异常:" + e.Message);
                throw new Exception(e.Message);
            
        

        /// <summary>
        /// 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="pStrCronExpress">触发器表达式</param>
        public static void ModifyJobTime(string pStrJobName, string pStrCronExpress, IDictionary<string, object> pDictionary)
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
                ICronTrigger trigger = (ICronTrigger)sched.GetTrigger(triggerKey);
                if (trigger == null)
                
                    return;
                
                RemoveJob(pStrJobName);
                addJob(pStrJobName, pStrCronExpress, pDictionary);
            
            catch (Exception e)
            
                throw new Exception(e.Message);
            
        
        #endregion

        #region 启动,关闭Job
        /// <summary>
        /// 启动所有定时任务
        /// </summary>
        public static void startJobs()
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                sched.Start();
            
            catch (Exception e)
            
                throw new Exception(e.Message);
            
        

        /// <summary>
        /// 关闭所有定时任务
        /// </summary>
        public static void ShutdownJobs()
        
            try
            
                IScheduler sched = schedulerFactory.GetScheduler();
                if (!sched.IsShutdown)
                
                    sched.Shutdown();
                
            
            catch (Exception e)
            
                throw new Exception(e.Message);
            
        
        #endregion

    

定制注册示例

 public partial class PubDataService : ServiceBase
    
        public PubDataService()
        
            InitializeComponent();
        

        protected override void OnStart(string[] args)
        
            try
            
                LogHelper.WriteLog("服务开始启动!");

                //定时生成病害检查自动任务数据连接服务(0.5时/次)
                QuartzManager<StcDiseaseManagerTask>.addJob("StcDiseaseManagerTask", ConfigHelper.GetAppSetting("cornExpress01"), new Dictionary<string, object>());
                QuartzManager<StcDiseaseManagerTask>.startJobs();//定时生成二次注浆区段自动任务数据连接服务(1月/次)
                #region 验证已通过
                QuartzManager<KeySectionSecondGroutSectionTask>.addJob<CalendarIntervalTriggerImpl>("KeySectionSecondGroutSectionTask",
                    d =>
                    
                        d.StartTimeUtc = DateBuilder.DateOf(23, 20, 0, 1, 1, 2023);
                        d.RepeatIntervalUnit = IntervalUnit.Month;
                        d.RepeatInterval = 1;
                        d.PreserveHourOfDayAcrossDaylightSavings = true;
                        return d;
                    ,
                    new Dictionary<string, object>());
                #endregion
                QuartzManager<KeySectionSecondGroutSectionTask>.startJobs();

                //定时生成技术状况2级及以上影响区段自动任务数据连接服务(1月/次)
                QuartzManager<KeySectionTechnicalValueSectionTask>.addJob("KeySectionTechnicalValueSectionTask", ConfigHelper.GetAppSetting("cornExpress04"), new Dictionary<string, object>());
                QuartzManager<KeySectionTechnicalValueSectionTask>.startJobs();

                //定时生成技术状况评定计算连接服务-单环评定(1日/次)
                QuartzManager<TecConditionSingleDataTask>.addJob("TecConditionSingleDataTask", ConfigHelper.GetAppSetting("cornExpress05"), new Dictionary<string, object>());
                QuartzManager<TecConditionSingleDataTask>.startJobs();

                //定时生成技术状况评定计算连接服务-区段评定(2周/次)
                #region 验证已通过
                QuartzManager<TecConditionStcSectionTask>.addJob<CalendarIntervalTriggerImpl>("TecConditionStcSectionTask",
                    d =>
                    
                        d.StartTimeUtc = DateBuilder.DateOf(23, 30, 0, 1, 1, 2023);
                        d.RepeatIntervalUnit = IntervalUnit.Week;
                        d.RepeatInterval = 2;
                        d.PreserveHourOfDayAcrossDaylightSavings = true;
                        return d;
                    ,
                    new Dictionary<string, object>());
                #endregion
                QuartzManager<TecConditionStcSectionTask>.startJobs();


                LogHelper.WriteLog("服务启动成功!");
            
            catch (Exception ex)
            
                LogHelper.WriteLog("服务启动失败," + ex.Message, ex);
            
        
        protected override void OnStop()
        
            LogHelper.WriteLog("服务开始关闭!");
            QuartzManager<StcDiseaseManagerTask>.ShutdownJobs();
            QuartzManager<StcDiseaseManagerTask>.RemoveJob("StcDiseaseManagerTask");

            QuartzManager<ElectroManagerTask>.ShutdownJobs();
            QuartzManager<ElectroManagerTask>.RemoveJob("ElectroManagerTask");

            QuartzManager<KeySectionSecondGroutSectionTask>.ShutdownJobs();
            QuartzManager<KeySectionSecondGroutSectionTask>.RemoveJob("KeySectionSecondGroutSectionTask");

            QuartzManager<KeySectionTechnicalValueSectionTask>.ShutdownJobs();
            QuartzManager<KeySectionTechnicalValueSectionTask>.RemoveJob("KeySectionTechnicalValueSectionTask");

            QuartzManager<TecConditionSingleDataTask>.ShutdownJobs();
            QuartzManager<TecConditionSingleDataTask>.RemoveJob("TecConditionSingleDataTask");

            LogHelper.WriteLog("服务关闭成功!");
        
    

 

Quartz.Net系列:Trigger之CalendarIntervalScheduleBuilder详解

所有方法图

技术图片

 

 CalendarIntervalScheduleBuilder方法

在SimpleScheduleBuilder基础上实现了日、周、月、年

WithInterval:指定要生成触发器的时间单位和间隔。

WithIntervalInHours:指定要生成触发器的间隔按小时来

WithIntervalInMinutes:指定要生成触发器的间隔按分钟来

WithIntervalInSeconds:指定要生成触发器的间隔按秒来

WithIntervalInDays:指定要生成触发器的间隔按日来

WithIntervalInWeeks:指定要生成触发器的间隔按周来

WithIntervalInMonths:指定要生成触发器的间隔按月来

WithIntervalInYears:指定要生成触发器的间隔按年来

            var trigger = TriggerBuilder.Create().WithCalendarIntervalSchedule(c=>c .WithInterval(1, IntervalUnit.Millisecond)
                                                                                    .WithIntervalInSeconds(1)
                                                                                    .WithIntervalInMinutes(1)
                                                                                    .WithIntervalInHours(1)
                                                                                    .WithIntervalInDays(1)
                                                                                    .WithIntervalInWeeks(1)
                                                                                    .WithIntervalInMonths(1)
                                                                                    .WithIntervalInYears(1)).Build();

注:按最后一个设定时间为准

最后指定给字段interval和intervalUnit,那么前面就会覆盖

在不指定间隔的时候默认是1,间隔单位是一天

    public class CalendarIntervalScheduleBuilder : ScheduleBuilder<ICalendarIntervalTrigger>
    {
        private int interval = 1;
        private IntervalUnit intervalUnit = IntervalUnit.Day;

        private int misfireInstruction = MisfireInstruction.SmartPolicy;
        private TimeZoneInfo timeZone;
        private bool preserveHourOfDayAcrossDaylightSavings;
        private bool skipDayIfHourDoesNotExist;
    }

 

 

技术图片

 

 

    /// <summary>
    /// Supported interval units used by <see cref="ICalendarIntervalTrigger" />.
    /// </summary>
    public enum IntervalUnit
    {
        Millisecond,
        Second,
        Minute,
        Hour,
        Day,
        Week,
        Month,
        Year
    }

 

 

       /// <summary>
        /// Specify the time unit and interval for the Trigger to be produced.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="interval">the interval at which the trigger should repeat.</param>
        /// <param name="unit"> the time unit (IntervalUnit) of the interval.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithInterval(int interval, IntervalUnit unit)
        {
            ValidateInterval(interval);
            this.interval = interval;
            intervalUnit = unit;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.SECOND that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInSeconds">the number of seconds at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInSeconds(int intervalInSeconds)
        {
            ValidateInterval(intervalInSeconds);
            interval = intervalInSeconds;
            intervalUnit = IntervalUnit.Second;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.MINUTE that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInMinutes">the number of minutes at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInMinutes(int intervalInMinutes)
        {
            ValidateInterval(intervalInMinutes);
            interval = intervalInMinutes;
            intervalUnit = IntervalUnit.Minute;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.HOUR that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInHours">the number of hours at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInHours(int intervalInHours)
        {
            ValidateInterval(intervalInHours);
            interval = intervalInHours;
            intervalUnit = IntervalUnit.Hour;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.DAY that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInDays">the number of days at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInDays(int intervalInDays)
        {
            ValidateInterval(intervalInDays);
            interval = intervalInDays;
            intervalUnit = IntervalUnit.Day;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.WEEK that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInWeeks">the number of weeks at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInWeeks(int intervalInWeeks)
        {
            ValidateInterval(intervalInWeeks);
            interval = intervalInWeeks;
            intervalUnit = IntervalUnit.Week;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.MONTH that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInMonths">the number of months at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInMonths(int intervalInMonths)
        {
            ValidateInterval(intervalInMonths);
            interval = intervalInMonths;
            intervalUnit = IntervalUnit.Month;
            return this;
        }

        /// <summary>
        /// Specify an interval in the IntervalUnit.YEAR that the produced
        /// Trigger will repeat at.
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="intervalInYears">the number of years at which the trigger should repeat.</param>
        /// <returns>the updated CalendarIntervalScheduleBuilder</returns>
        /// <seealso cref="ICalendarIntervalTrigger.RepeatInterval" />
        /// <seealso cref="ICalendarIntervalTrigger.RepeatIntervalUnit" />
        public CalendarIntervalScheduleBuilder WithIntervalInYears(int intervalInYears)
        {
            ValidateInterval(intervalInYears);
            interval = intervalInYears;
            intervalUnit = IntervalUnit.Year;
            return this;
        }

InTimeZone:设置时区

 var trigger = TriggerBuilder.Create().WithCalendarIntervalSchedule(c => c.InTimeZone(TimeZoneInfo.Local)).Build();

 

以上是关于Quartz.Net间隔N周/日/年定时触发器写法总结的主要内容,如果未能解决你的问题,请参考以下文章

Quartz.NET 入门

Quartz.NET总结Quartz 远程调度

定时任务之cron

定时任务框架-quartz 时间配置

quartz定时任务时间设置

JAVA 定时器时间格式