zoukankan      html  css  js  c++  java
  • Quartz.NET 作业调度

    Quartz 简介:

    Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等

    Quartz.NET允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。

    整合了 Quartz.NET的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。

    使用Quartz

           一旦调度程序被实例化,它就可以启动,处于待机模式并关闭。请注意,一旦调度程序关闭,就不能在不重新实例化的情况下重新启动它。在调度程序启动之前,触发器不会触发(作业不执行),也不会在处于暂停状态时触发。

    简单案例:

    using Quartz;
    using Quartz.Impl;
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleQuartz
    {
        class Program
        {
            static void Main(string[] args)
            {
                // trigger async evaluation
                RunProgramRunExample().GetAwaiter().GetResult();
    
                Console.WriteLine("Press any key to close the application");
                Console.ReadKey();
            }
    
    
            private static async Task RunProgramRunExample()
            {
                try
                {
                    // Grab the Scheduler instance from the Factory
                    NameValueCollection props = new NameValueCollection
                    {
                        { "quartz.serializer.type", "binary" }
                    };
                    StdSchedulerFactory factory = new StdSchedulerFactory(props);
                    // get a scheduler
                    IScheduler scheduler = await factory.GetScheduler();
    
                    // and start it off
                    await scheduler.Start();
    
                    // define the job and tie it to our HelloJob class
                    IJobDetail job = JobBuilder.Create<HelloJob>()
                        .WithIdentity("job1", "group1")
                        .Build();
    
                    // Trigger the job to run now, and then repeat every 10 seconds
                    ITrigger trigger = TriggerBuilder.Create()
                        .WithIdentity("trigger1", "group1")
                        .StartNow()
                        .WithSimpleSchedule(x => x
                            .WithIntervalInSeconds(10)
                            .RepeatForever())
                        .Build();
    
                    // Tell quartz to schedule the job using our trigger
                    await scheduler.ScheduleJob(job, trigger);
    
                    // some sleep to show what's happening
                    await Task.Delay(TimeSpan.FromSeconds(60));
    
                    // and last shut down the scheduler when you are ready to close your program
                    await scheduler.Shutdown();
                }
                catch (SchedulerException se)
                {
                    Console.WriteLine(se);
                }
            }
        }
    }
    public class HelloJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            await Console.Out.WriteLineAsync("HelloJob is executing.");
        }
    }

    Quartz API的关键接口和类是:

    • IScheduler - 与调度程序交互的主要API。
    • IJob - 由您希望由调度程序执行的组件实现的接口。
    • IJobDetail - 用于定义Jobs的实例。
    • ITrigger - 一个组件,用于定义执行给定作业的计划。
    • JobBuilder - 用于定义/构建JobDetail实例,用于定义Jobs的实例。
    • TriggerBuilder - 用于定义/构建触发器实例。

    工作和触发器

    Job是一个实现IJob接口的类,它只有一个简单的方法:

    IJob接口

        namespace Quartz
        {
            public interface IJob
            {
                Task Execute(JobExecutionContext context);
            }
        }

     

    身份标识:

         作业和触发器在Quartz 调度程序注册时被赋予标识。作业和触发器的键JobKey和TriggerKey)允许将它们放入“组”中。

         作业或触发器的键的名称部分在组内必须是唯一的。

    • 换句话说,作业或触发器的完整键(或标识符)是名称和组的组合。

    如何为Job实例提供属性/配置 或 如何在执行之间跟踪作业的状态?

    通过JobDataMap ,它是JobDetail对象的一部分。

    JobDataMap 简介:

    JobDataMap 可用于保存在Job实例执行时,可用的任意数量(可序列化)对象。JobDataMap是IDictionary接口的一个实现,并且具有一些用于存储和检索基本类型数据的便利方法。

    JobDataMap中设置值

    // define the job and tie it to our DumbJob classI
    JobDetail job = JobBuilder.Create<DumbJob>()
    .WithIdentity("myJob", "group1") // name "myJob", group "group1" .UsingJobData("jobSays", "Hello World!") .UsingJobData("myFloatValue", 3.141f) .Build();

    Job执行期间 JobDataMap获取值

    public class DumbJob : IJob{
        public async Task Execute(IJobExecutionContext context)
        {
            JobKey key = context.JobDetail.Key;
            JobDataMap dataMap = context.JobDetail.JobDataMap;
            string jobSays = dataMap.GetString("jobSays");
            float myFloatValue = dataMap.GetFloat("myFloatValue");
            await Console.Error.WriteLineAsync("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
        }}

    日历

    实现ICalendar接口的Quartz.NET Calendar对象可以在触发器存储在调度程序中时与触发器相关联。日历可用于从触发器的发射计划中排除时间块。例如,您可以创建一个触发器,在每个工作日上午9:30触发作业,但随后添加一个排除所有业务假期的日历。


    必须通过AddCalendar(..)方法实例化日历并向调度程序注册日历。如果您使用HolidayCalendar,则在实例化之后,您应该使用其AddExcludedDate(DateTime date)方法,以便使用您希望从计划中排除的日期填充它。相同的日历实例可以与多个触发器一起使用

    日历示例 将跳过在日历排除的期间内发生的任何发射。

     

        HolidayCalendar cal = new HolidayCalendar();
        cal.AddExcludedDate(someDate);
        
        await sched.AddCalendar("myHolidays", cal, false);
        
        ITrigger t = TriggerBuilder.Create()
            .WithIdentity("myTrigger")
            .ForJob("myJob")
            .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
            .ModifiedByCalendar("myHolidays") // but not on holidays
            .Build();
        // .. schedule job with trigger
        ITrigger t2 = TriggerBuilder.Create()
            .WithIdentity("myTrigger2")
            .ForJob("myJob2")
            .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
            .ModifiedByCalendar("myHolidays") // but not on holidays
            .Build();

     

    SimpleTrigger

    如果您需要在特定时刻执行一次作业,或者在特定时刻执行作业,然后按特定时间间隔重复,则SimpleTrigger应满足您的日程安排需求。例如:你想让触发器在2005年1月13日上午11:23:54发射,那么每10秒再发射5次

     

    SimpleTrigger的属性包括:开始时间,结束时间,重复计数和重复间隔

    重复计数可以是零,正整数或常量值SimpleTrigger.RepeatIndefinitely。

    重复间隔属性必须是TimeSpan.Zero或正TimeSpan值。

    请注意,重复间隔为零将导致触发器的“重复计数”触发同时发生(或者与调度程序可以管理的同时接近)

     

    SimpleTrigger实例是使用TriggerBuilder(用于触发器的主要属性)和WithSimpleSchedule扩展方法(用于SimpleTrigger特定属性)构建的。

    在特定时刻构建触发器,不重复:

     

    // trigger builder creates simple trigger by default, actually an ITrigger is returnedISimpleTrigger trigger = (ISimpleTrigger) TriggerBuilder.Create()
        .WithIdentity("trigger1", "group1")
        .StartAt(myStartTime) // some Date 
        .ForJob("job1", "group1") // identify job with name, group strings
        .Build();

     

    在特定时刻构建触发器,然后每十秒重复十次:

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .StartAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
        .WithSimpleSchedule(x => x
            .WithIntervalInSeconds(10)
            .WithRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
        .ForJob(myJob) // identify job with handle to its JobDetail itself                   
        .Build();

    构建一个触发器,将在未来五分钟内触发:

     

    trigger = (ISimpleTrigger) TriggerBuilder.Create()
        .WithIdentity("trigger5", "group1")
        .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Minute)) // use DateBuilder to create a date in the future
        .ForJob(myJobKey) // identify job with its JobKey
        .Build();

     

    构建一个现在将触发的触发器,然后每五分钟重复一次,直到22:00:

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger7", "group1")
        .WithSimpleSchedule(x => x
            .WithIntervalInMinutes(5)
            .RepeatForever())
        .EndAt(DateBuilder.DateOf(22, 0, 0))
        .Build();

    构建一个触发器,在下一个小时的顶部触发,然后每2小时重复一次,永远:

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
        .StartAt(DateBuilder.EvenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
        .WithSimpleSchedule(x => x
            .WithIntervalInHours(2)
            .RepeatForever())
        // note that in this example, 'forJob(..)' is not called 
        //  - which is valid if the trigger is passed to the scheduler along with the job  
        .Build();await scheduler.scheduleJob(trigger, job);

    CronTrigger

    CronTriggers通常比SimpleTrigger更有用,如果您需要基于类似日历的概念而不是精确指定的SimpleTrigger间隔重复发生的作业计划。

    使用CronTrigger,您可以指定触发时间表,例如“每周五中午”,或“每个工作日和上午9:30”,甚至“每周一,周三上午9:00到上午10:00之间每隔5分钟”和星期五”。

    即便如此,像SimpleTrigger一样,CronTrigger有一个startTime,用于指定计划何时生效,以及一个(可选的)endTime,用于指定何时停止计划。

     

    Cron表达式

    Cron-Expressions用于配置CronTrigger的实例。Cron-Expressions是实际上由七个子表达式组成的字符串,用于描述计划的各个细节。这些子表达式用空格分隔,表示:

    1. 分钟
    2. 小时
    3. 日的日
    4. 某一天的周
    5. 年份(可选字段)

     建立CronTriggers

     CronTrigger实例是使用TriggerBuilder(用于触发器的主要属性)和WithCronSchedule扩展方法(用于特定于CronTrigger的属性)构建的。

     您还可以使用CronScheduleBuilder的静态方法来创建计划。

    建立一个触发器,每天上午8点到下午5点之间每隔一分钟触发一次:

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .WithCronSchedule("0 0/2 8-17 * * ?")
        .ForJob("myJob", "group1")
        .Build();

    构建一个触发器,每天上午10:42开火:

    // we use CronScheduleBuilder's static helper methods heretrigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 42))
        .ForJob(myJobKey)
        .Build();

    要么 -

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .WithCronSchedule("0 42 10 * * ?")
        .ForJob("myJob", "group1")
        .Build();

    构建一个触发器,该触发器将在星期三上午10点42分在TimeZone中触发,而不是系统的默认值:

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .WithSchedule(CronScheduleBuilder
            .WeeklyOnDayAndHourAndMinute(DayOfWeek.Wednesday, 10, 42)
            .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
        .ForJob(myJobKey)
        .Build();

    要么 -

    trigger = TriggerBuilder.Create()
        .WithIdentity("trigger3", "group1")
        .WithCronSchedule("0 42 10 ? * WED", x => x
            .InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
        .ForJob(myJobKey)
        .Build();

    示例Cron表达式

    以下是表达式及其含义的更多示例 - 您可以在CronTrigger的API文档中找到更多

    CronTrigger示例1 - 用于创建触发器的表达式,该触发器每5分钟触发一次

    "0 0/5 * * * ?"

    CronTrigger示例2 - 用于创建触发器的表达式,该触发器在每分钟10秒后(即上午10:00:10,上午10:05:10等)每隔5分钟触发一次。

    "10 0/5 * * * ?"

    CronTrigger示例3 - 用于创建触发器的表达式,该触发器在每周三和周五的10:30,11:30,12:30和13:30触发。

    "0 30 10-13 ? * WED,FRI"

    CronTrigger示例4 - 用于创建触发器的表达式,该触发器在每个月的5日和20日上午8点到上午10点之间每半小时触发一次。请注意,触发器不会在上午10:00,即8:00,8:30,9:00和9:30触发

    "0 0/30 8-9 5,20 * ?"

    请注意,某些计划要求过于复杂,无法通过单个触发器表达 - 例如“上午9:00至上午10:00之间每隔5分钟,下午1:00至晚上10:00之间每20分钟”。此方案中的解决方案是简单地创建两个触发器,并注册它们以运行相同的作业

     

  • 相关阅读:
    php中防止SQL注入的方法
    谈谈asp,php,jsp的优缺点
    SSH原理与运用(一):远程登录
    优化MYSQL数据库的方法
    json_encode和json_decode区别
    静态方法与非静态方法的区别
    Java 异常的Exception e中的egetMessage()和toString()方法的区别
    $GLOBALS['HTTP_RAW_POST_DATA'] 和$_POST的区别
    HTML5开发,背后的事情你知道吗?
    使用C语言来实现模块化
  • 原文地址:https://www.cnblogs.com/AndyChen2015/p/9571533.html
Copyright © 2011-2022 走看看