zoukankan      html  css  js  c++  java
  • Quartz.NET

    使用 Topshelf 结合 Quartz.NET 创建 Windows 服务

    • Ø  前言

    之前一篇文章已经介绍了,如何使用 Topshelf 创建 Windows 服务。当时提到还缺少一个任务调度框架,就是 Quartz.NET。而本文就展开对 Quartz.NET 的研究,以及如何使用 Topshelf 结合 Quartz.NET 运行一个定时的 Windows 服务。

     

    • Ø  本文主要内容
    1. 1.   搭建 Topshelf 的运行环境。
    2. 2.   编写一个存储过程,用于更新商品表中的库存。
    3. 3.   安装 Quartz 所需的 dll 文件。
    4. 4.   创建 Quartz 的配置文件。
    5. 5.   创建 Windwos 服务调度程序。
    6. 6.   创建作业类,实现 IJob 接口。
    7. 7.   开启 Windows 服务。

     

    1. 1.   搭建 Topshelf 的运行环境

    1)   创建一个控制台应用程序。

    2)   添加 Topshelf 相关的 dll 的引用,可参考使用 Topshelf 创建 Windows 服务

     

    1. 2.   编写一个存储过程,用于更新商品表中的库存

    1)   首先,创建一张商品表 Goods

    IF(OBJECT_ID('Goods', 'U') IS NOT NULL)

        DROP TABLE Goods;

    GO

    CREATE TABLE Goods

    (

        Id int IDENTITY(1, 1) NOT NULL,

        Name nvarchar(30) NOT NULL,

        Inventory int NOT NULL

        CONSTRAINT PK_Goods_Id PRIMARY KEY CLUSTERED

        (

            Id ASC

        ) ON [PRIMARY]

    ) ON [PRIMARY];

    INSERT INTO Goods VALUES('大米', 0),('香蕉', 0),('苹果', 0);

    SELECT * FROM Goods;

     

     

    2)   然后,创建存储过程 proc_UpdateInventory

    IF(OBJECT_ID('proc_UpdateInventory', 'P') IS NOT NULL)

        DROP PROCEDURE proc_UpdateInventory;

    GO

    CREATE PROCEDURE proc_UpdateInventory(@GoodsId int, @Inventory int)

    AS

        UPDATE Goods SET Inventory=@Inventory WHERE Id=@GoodsId;

    GO

     

    1. 3.   安装 Quartz 所需的 dll 文件

    1)   安装 Quartz,控制台输入:Install-Package Quartz

    2)   安装 Common.Logging.Log4Net1211,控制台输入:Install-Package Common.Logging.Log4Net1211

    3)   安装成功后,将看到如下图的引用及配置:

     

     

    1. 4.   创建 Quartz 的配置文件
    • Ø  注意:必须将以下配置文件的“复制到输出目录”设置为始终复制。
    • Ø  关于 Quartz 的配置可参考:Quartz.NET 配置文件详解

    1)   创建 quartz.config 文件,编辑内容:

    # You can configure your scheduler in either<quartz> configuration section

    # or in quartz properties file

    # Configuration section has precedence

     

    quartz.scheduler.instanceName = TopshelfAndQuartz

     

    # configure thread pool info

    quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz

    quartz.threadPool.threadCount = 10

    quartz.threadPool.threadPriority = Normal

     

    # job initialization plugin handles our xml reading, without it defaults are used

    quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz

    quartz.plugin.xml.fileNames = ~/quartz_jobs.xml

     

    # export this server to remoting context

    #quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz

    #quartz.scheduler.exporter.port = 555

    #quartz.scheduler.exporter.bindName = QuartzScheduler

    #quartz.scheduler.exporter.channelType = tcp

    #quartz.scheduler.exporter.channelName = httpQuartz

     

    2)   创建 quartz_jobs.xml 文件,编辑内容:

    <?xml version="1.0" encoding="UTF-8"?>

     

    <!-- This file contains job definitions in schema version 2.0 format -->

    <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">

     

      <processing-directives>

        <overwrite-existing-data>true</overwrite-existing-data>

      </processing-directives>

     

      <schedule>

        <!--该作业用于定时更新商品库存-->

        <job>

          <name>UpdateInventoryJob</name>

          <group>Update</group>

          <description>定时更新商品库存</description>

          <job-type>TopshelfAndQuartz.UpdateInventoryJob,TopshelfAndQuartz</job-type>

          <durable>true</durable>

          <recover>false</recover>

        </job>

        <trigger>

          <cron>

            <name>UpdateInventoryTrigger</name>

            <group>Update</group>

            <job-name>UpdateInventoryJob</job-name>

            <job-group>Update</job-group>

            <start-time>2017-12-01T00:00:00+08:00</start-time>

            <cron-expression>0 0/1 * * * ?</cron-expression>

          </cron>

        </trigger>

      </schedule>

     

    </job-scheduling-data>

    • Ø  该文件用于定义每个作业及触发行为。

     

    1. 5.   创建 Windwos 服务调度程序

    4)   这里的调度程序是指,当 Windows 服务启动或停止后,通知 Quartz 调度程序做响应的操作,代码如下:

    /// <summary>

    /// 服务运行时。

    /// </summary>

    public class ServiceRunner : ServiceControlServiceSuspend

    {

        private readonly IScheduler Scheduler = StdSchedulerFactory.GetDefaultScheduler();

     

        public bool Start(HostControl hostControl)

        {

            //开始调度作业

            Scheduler.Start();

            Log.Logger.Info("开始调度作业");

            return true;

        }

     

        public bool Stop(HostControl hostControl)

        {

            //停止调度作业

            Scheduler.Shutdown(false);  //false: 表示当停止服务时,所有正则在执行的作业也立即停止

            Log.Logger.Info("停止调度作业");

            return true;

        }

     

        public bool Continue(HostControl hostControl)

        {

            //所有调度作业重新开始

            Scheduler.ResumeAll();

            Log.Logger.Info("所有调度作业重新开始");

            return true;

        }

     

        public bool Pause(HostControl hostControl)

        {

            //暂停所有调度作业

            Scheduler.ResumeAll();

            Log.Logger.Info("暂停所有调度作业");

            return true;

        }

    }

    5)   注意:只有实现了 ServiceSuspend 接口,服务才支持暂停与恢复操作,否则会报错。

     

    1. 6.   创建作业类,实现 IJob 接口

    6)   当作业被触发时,将调用对应作业的 Execute() 方法。

    /// <summary>

    /// 更新库存作业。

    /// </summary>

    public class UpdateInventoryJob : IJob

    {

        /// <summary>

        /// 作业被触发时执行该方法。

        /// </summary>

        public void Execute(IJobExecutionContext context)

        {

            try

            {

                //模拟调用存储过程,更新商品库存

                string connStr = @"Data Source=127.0.0.1MYMSSQLSERVER08;Initial Catalog=MyDB;Persist Security Info=True;User ID=sa;Password=xxxxxx;";

                using (SqlConnection conn = new SqlConnection(connStr))

                {

                    using (SqlCommand cmd = new SqlCommand())

                    {

                        conn.Open();

                        cmd.Connection = conn;

                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.CommandText = "proc_UpdateInventory";

                        Random random = new Random();

                        SqlParameter[] paras = new SqlParameter[]

                        {

                            new SqlParameter()

                            {

                                ParameterName = "@GoodsId",

                                SqlDbType = SqlDbType.Int,

                                Value =  random.Next(1, 4)

                            },

                            new SqlParameter()

                            {

                                ParameterName = "@Inventory",

                                SqlDbType = SqlDbType.Int,

                                Value = random.Next(1, 100)

                            }

                        };

                        cmd.Parameters.AddRange(paras);

                        int rowCount = cmd.ExecuteNonQuery();   //exec proc_UpdateInventory @GoodsId=1,@Inventory=25

                        if (rowCount > 0)

                            Log.Logger.InfoFormat("商品:{0},库存已更新,新的库存为:{1}", paras[0].Value, paras[1].Value);

                        else

                            Log.Logger.InfoFormat("更新商品库失败,无受影响记录:{0}", rowCount);

                    }

                }

            }

            catch (Exception ex)

            {

                Log.Logger.ErrorFormat("UpdateInventoryJob 作业执行异常:{0}", ex);

            }

        }

    }

     

    1. 7.   开启 Windows 服务

    1)   首先在 Main() 方法中加入如下代码:

    static void Main(string[] args)

    {

        var configFile = new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config"));

        log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);

     

        Log.Logger.Info("服务开始运行");

        HostFactory.Run(o =>

        {

            //o.UseLog4Net(); //这里需要使用 log4net, Version=1.2.15.0 的版本,当前版本不兼容所以注释掉

            o.Service<ServiceRunner>();

            o.SetServiceName("TopshelfAndQuartzService");

            o.SetDisplayName("库存更新服务");

            o.SetDescription("该服务用于定时更新商品库存");

            o.EnablePauseAndContinue();

        });

    }

    2)   安装服务并启动

    安装服务的具体操作可参考:使用 Topshelf 创建 Windows 服务

    3)   启动服务后,等待3分钟,依次对服务进行暂停 -> 恢复 -> 停止操作,将看到如下结果:

    1. 1.   Log

     

    1. 2.   Data

     

     

    • Ø  总结

    本文,使用 Topshelf 结合 Quartz 搭建了一个 Windows 服务,用于定时调用存储过程更新商品库存。可见 Topshelf 与 Quartz 的结合是天衣无缝,非常适合在平时的开发工作中。

     

     

     

    Quartz.NET 配置文件详解

      前言

    在之前的 使用 Topshelf 结合 Quartz.NET 创建 Windows 服务 文章中,使用到了 Quartz 的两个配置文件 quartz.config 和 quartz_jobs.xml。由于篇幅原因,没有细说,这里再说明下。本人觉得 Quertz 的强大之处莫过于他的配置文件,所以有必要深入理解下。

     

    1. 1.   首先,说说 quartz.config 文件

    1)   先将上一篇中的配置贴出来

    # You can configure your scheduler in either<quartz> configuration section

    # or in quartz properties file

    # Configuration section has precedence

     

    quartz.scheduler.instanceName = TopshelfAndQuartz

     

    # configure thread pool info

    quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz

    quartz.threadPool.threadCount = 10

    quartz.threadPool.threadPriority = Normal

     

    # job initialization plugin handles our xml reading, without it defaults are used

    quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz

    quartz.plugin.xml.fileNames = ~/quartz_jobs.xml

     

    # export this server to remoting context

    #quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz

    #quartz.scheduler.exporter.port = 555

    #quartz.scheduler.exporter.bindName = QuartzScheduler

    #quartz.scheduler.exporter.channelType = tcp

    #quartz.scheduler.exporter.channelName = httpQuartz

     

    2)   以上标注为红色的配置修改的可能性相对较大。

    1. 1.   quartz.scheduler.instanceName 指定调度器的实例名称。
    2. 2.   quartz.threadPool.threadCount 设置线程池的最大线程数量。
    3. 3.   quartz.threadPool.threadPriority 设置作业中每个线程的优先级,可取 System.Threading.ThreadPriority 中的枚举。
    4. 4.   quartz.plugin.xml.fileNames 指定 Quartz 的作业配置文件路径及名称,以上指定为 quartz_jobs.xml,默认情况下命名为该名称即可。

     

    3)   其他的没什么说的,因为以上配置是 Quartz 的标准配置,如没有特殊要求是不需要修改的。所以,这里一带而过,以后有必要时再来研究它。

     

    1. 2.   然后,是 quartz_jobs.xml文件

    1)   同样,以上篇的配置为例:

    <?xml version="1.0" encoding="UTF-8"?>

     

    <!-- This file contains job definitions in schema version 2.0 format -->

    <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">

     

      <processing-directives>

        <overwrite-existing-data>true</overwrite-existing-data>

      </processing-directives>

     

      <schedule>

        <!--该作业用于定时更新商品库存-->

        <job>

          <name>UpdateInventoryJob</name>

          <group>Update</group>

          <description>定时更新商品库存</description>

          <job-type>TopshelfAndQuartz.UpdateInventoryJob,TopshelfAndQuartz</job-type>

          <durable>true</durable>

          <recover>false</recover>

        </job>

        <trigger>

          <cron>

            <name>UpdateInventoryTrigger</name>

            <group>Update</group>

            <job-name>UpdateInventoryJob</job-name>

            <job-group>Update</job-group>

            <start-time>2017-12-01T00:00:00+08:00</start-time>

            <cron-expression>0 0/1 * * * ?</cron-expression>

          </cron>

        </trigger>

      </schedule>

     

    </job-scheduling-data>

     

    2)   这个配置文件相当重要,所有作业的调度都是由该文件定义的。其中最重要的节点是 cron-expression 和 repeat-interval 节点,下面是每个节点的具体说明:

    1. 1.   job 作业节点,每个作业则对应一个 job 节点。

    1)   name(必填)        作业名称,同一个 group 中作业名称不能相同。

    2)   group(选填)       作业分组名称,表示该作业所属分组。

    3)   description(选填) 作业描述,用于描述该作业的具体功能。

    4)   job-type(必填)    指定作业将调用的作业实现类,格式为:命名空间.类名,程序集名称。

    5)   durable(选填)     表示该作业是否长久的,具体作用不详,默认为true。

    6)   recover(选填)     字面意思是恢复,具体作用不详,默认为false。

     

    1. 2.   trigger 作业触发器节点,用于定义指定的作业以何种方式触发,一个作业可以有多个触发器,而每个触发器都独立执行调度。
    • Ø  触发器可以为以下三种类型:

    1)   calendar-interval 这种触发器类型使用较少,此处省略。

    2)   simple 简单触发器,可用于调度重复执行的作业。

    1. 1.   name(必填)        触发器名称,同一个 group 中作业名称不能相同。
    2. 2.   group(选填)       触发器分组名称,表示该触发器所属分组。
    3. 3.   job-name(必填)    要调度的作业名称,必须与 job 节点中的 name 相同。
    4. 4.   job-group(选填)   要调度的作业分组名称,必须与 job 节点中的 group 相同。
    5. 5.   start-time(选填)  开始作业的 utc 时间,北京时间需要+08:00,例如:<start-time>2017-12-01T08:00:00+08:00</start-time>,表示北京时间2017年12月1日上午8:00开始执行。注意:服务启动或重启时都会检测此属性。若没有设置此属性或者 start-time 的时间小于当前时间,服务启动后会立即执行一次调度;若大于当前时间,服务会等到当前时间等于 start-time 的时间才开始执行。如果没有特殊要求,可以忽略该属性。
    6. 6.   repeat-count(选填)表示作业重复执行次数,-1表示无限制重复执行,3 表示作业重复执行三次。
    7. 7.   repeat-interval(必填)表示作业触发间隔时间,10000 表示十秒触发一次,单位:毫秒。
    8. 8.   示例:

    <simple>

      <name>UpdateInventoryTrigger</name>

      <group>Update</group>

      <job-name>UpdateInventoryJob</job-name>

      <job-group>Update</job-group>

      <start-time>2017-12-01T00:00:00+08:00</start-time>

      <repeat-count>3</repeat-count>

      <repeat-interval>10000</repeat-interval>

    </simple>

    以上配置将在服务启动后,每十秒触发一次作业,共触发三次,如图:

     

     

    1)   cron 复杂触发器,使用 cron-expression 设置触发器的行为。

    1. 1.   name                与 simple 相同。
    2. 2.   group               与 simple 相同。
    3. 3.   job-name            与 simple 相同。
    4. 4.   job-group           与 simple 相同。
    5. 5.   start-time          开始作业的 utc 时间,北京时间需要+08:00,例如:<start-time>2017-12-01T08:00:00+08:00</start-time>,表示北京时间2017年12月1日上午8:00开始执行。注意:服务启动或重启时都会检测此属性。若没有设置此属性,服务会根据 cron-expression 的规则执行作业调度;若 start-time 的时间小于当前时间,服务启动后会忽略 cron-expression 的设置,立即执行一次调度,之后再根据 cron-expression 执行作业调度;若大于当前时间,服务会等到当前时间等于 start-time 的时间才开始执行,并根据 cron-expression 执行作业调度。如果没有特殊要求,可以忽略该属性。
    6. 6.   cron-expression(必填)cron 表达式,例如:<cron-expression>0 0/1 * * * ?</cron-expression>,表示间隔1分钟触发一次。注意:该节点为必须,如果省略整个服务将不能正常运行!

     

    1. 3.   详解 cron-expression 节点
    • Ø  这个节点的设置相对复杂很多,因为所有的触发需求都是由该节点来控制,比如(未经测试):
    1. 1.   每月1号1点触发一次,表达式:0 0 1 1 * *
    2. 2.   每周日12点触发一次,表达式:0 0 12 ? * SUN
    3. 3.   每天9点到18点每小时触发一次,表达式:0 0 9-18 * * ?

     

    • Ø  详细说明
    1. 1.   一个cron表达式有至少6个(或7个)由空格分隔的时间元素,按顺序依次为:[秒] [分] [小时] [日] [月] [周] [年]

    元素    必填        取值范围                通配符

    秒     是          0~59                    , - * /

    分     是          0~59                    , - * /

    时      是          0~23                    , - * /

    日     是          1~31                    , - * ? / L W

    月     是          0-11 or JAN-DEC         , - * /

    周     是           1-7 or SUN-SAT          , - * ? / L #

    年     否           empty or 1970-2099      , - * /

    其中,周取值:1=周日~7=周六,1=SUN,2=MON,3=TUE,4=WED,5=THU,6=FRI,7=SAT。

     

    1. 2.   通配符说明:

    1)   * 表示所有值,例如:分设置为"*",表示每一分钟都会触发。

    2)   ? 表示不指定值,使用场景不需要关心当前的这个元素。例如:要在每月的10号触发一个操作,但不关心是周几,所以周设置为"?",具体设置为 0 0 0 10 * ?。

    3)   表示区间,例如:在小时上设置"10-12",表示10,11,12点都会触发。注意:这里的区间是包头包围的,比如配置是:0 0/15 9-22 * * ?,则表示9:00~22:59,每15分钟触发一次。

    4)   , 表示指定多个值(列表),例如:在周字段上设置"MON,WED,FRI",表示周一、周三、周五都会触发。

    5)   / 用于递增触发,例如:在秒上面设置"5/15",表示从5秒开始,每增15秒触发一次(5,20,35,50)。

    6)   L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]);在周字段上表示星期六,相当于"7"或"SAT"。如果在"L"前加上数字,则表示该数据的最后一个。例如:在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五”。

    7)   W 表示离指定日期的最近那个工作日(周一至周五)。例如:在日字段上设置"15W",表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发,如果15号是周未,则找最近的下周一(16号)触发。如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为"1W",它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注:"W"前只能设置具体的数字,不允许区间"-")。

    8)   # 序号,表示每月的第几个周几。例如:在周字段上设置"6#3"表示在每月的第三个周六。注意如果指定"#5",正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了);小提示:'L'和'W'可以一组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同。

     

    1. 3.   常用示例:

    0 0 12 * * ?            每天12点触发

    0 15 10 ? * *           每天10点15分触发

    0 15 10 * * ?           每天10点15分触发

    0 15 10 * * ? *         每天10点15分触发

    0 0 12 ? * WED          每周三12点触发

    0 0/30 9-17 * * ?       每天九点到十五店,每半小时触发

    0 10,14,16 * * ?        每天上午10点,下午2点、4点触发

    0 15 10 * * ? 2005      2005年每天10点15分触发

    0 * 14 * * ?            每天下午的2点到2点59分每分触发

    0 0/5 14 * * ?          每天下午的2点到2点59分(整点开始,每隔5分触发)

    0 0/5 14,18 * * ?       每天下午的 2点到2点59分、18点到18点59分(整点开始,每隔5分触发)

    0 0-5 14 * * ?          每天下午的 2点到2点05分每分触发

    0 10,44 14 ? 3 WED      3月分每周三下午的 2点10分和2点44分触发

    0 15 10 ? * MON-FRI     从周一到周五每天上午的10点15分触发

    0 15 10 15 * ?          每月15号上午10点15分触发

    0 15 10 L * ?           每月最后一天的10点15分触发

    59 59 23 L * ?          每月最后一天的23点59分59秒触发(经测试)

    0 15 10 ? * 6L          每月最后一周的星期五的10点15分触发

    0 15 10 ? * 6L 2002-2005    从2002年到2005年每月最后一周的星期五的10点15分触发

    0 15 10 ? * 6#3         每月的第三周的星期五开始触发

    0 0 12 1/5 * ?          每月的第一个中午开始每隔5天触发一次

    0 11 11 11 11 ?         每年的11月11号 11点11分触发(光棍节)

     

    • Ø  总结

    本篇主要详细的学习了 Quartz 的相关配置,这应该是 Quartz 的重要知识点,要一下子记住这些配置是不太可能的。所以,还需要在以后的工作中多多运用才行。

     

     

     

     

     

    使用 Topshelf 结合 Quartz.NET 创建 Windows 服务

     

    http://www.cnblogs.com/abeam/p/8042531.html

     

    Quartz.NET 配置文件详解

     

    https://www.cnblogs.com/abeam/p/8044460.html

     

     

     

    Quartz.net 开源job调度框架(一)

     

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

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

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

     

     

     

    官方学习文档:http://www.quartz-scheduler.net/documentation/index.html

     

    使用实例介绍:http://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html

     

    官方的源代码下载:http://sourceforge.net/projects/quartznet/files/quartznet/   

    Quartz.Net入门(1)

    背景

    很多时候,项目需要在不同时刻,执行一个或很多个不同的作业。

    Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架。

    介绍

    Quartz一个开源的作业调度框架,OpenSymphony的开源项目。Quartz.Net 是Quartz的C#移植版本。

    它一些很好的特性:

    1:支持集群,作业分组,作业远程管理。 

    2:自定义精细的时间触发器,使用简单,作业和触发分离。

    3:数据库支持,可以寄宿Windows服务,WebSite,winform等。

    实战

    Quartz框架的一些基础概念解释:

       Scheduler     作业调度器。

       IJob             作业接口,继承并实现Execute, 编写执行的具体作业逻辑。

      JobBuilder       根据设置,生成一个详细作业信息(JobDetail)。

      TriggerBuilder   根据规则,生产对应的Trigger

     
    static void Main(string[] args)
           {
               //从工厂中获取一个调度器实例化
               IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
     
               scheduler.Start();       //开启调度器
     
               //==========例子1(简单使用)===========
     
               IJobDetail job1 = JobBuilder.Create<HelloJob>()  //创建一个作业
                   .WithIdentity("作业名称""作业组")
                   .Build();
     
               ITrigger trigger1 = TriggerBuilder.Create()
                                           .WithIdentity("触发器名称""触发器组")
                                           .StartNow()                        //现在开始
                                           .WithSimpleSchedule(x => x         //触发时间,5秒一次。
                                               .WithIntervalInSeconds(5)
                                               .RepeatForever())              //不间断重复执行
                                           .Build();
     
     
               scheduler.ScheduleJob(job1, trigger1);      //把作业,触发器加入调度器。
     
               //==========例子2 (执行时 作业数据传递,时间表达式使用)===========
     
               IJobDetail job2= JobBuilder.Create<DumbJob>()
                                           .WithIdentity("myJob""group1")
                                           .UsingJobData("jobSays""Hello World!")
                                           .Build();
     
     
               ITrigger trigger2 = TriggerBuilder.Create()
                                           .WithIdentity("mytrigger""group1")
                                           .StartNow()
                                           .WithCronSchedule("/5 * * ? * *")    //时间表达式,5秒一次     
                                           .Build();
     
     
               scheduler.ScheduleJob(job2, trigger2);     
             
               //scheduler.Shutdown();         //关闭调度器。
           }

    声明要执行的作业,HelloJob:

     
    /// <summary>
       /// 作业
       /// </summary>
       public class HelloJob : IJob
       {
           public void Execute(IJobExecutionContext context)
           {
               Console.WriteLine("作业执行!");
           }
       }

    声明要执行的作业,DumbJob:

     
    public class DumbJob : IJob
        {
            /// <summary>
            ///  context 可以获取当前Job的各种状态。
            /// </summary>
            /// <param name="context"></param>
            public void Execute(IJobExecutionContext context)
            {
     
                JobDataMap dataMap = context.JobDetail.JobDataMap;
     
                string content = dataMap.GetString("jobSays");
     
                Console.WriteLine("作业执行,jobSays:" + content);
            }
        }

    其WithCronSchedule("") 拥有强大的Cron时间表达式,正常情况下WithSimpleSchedule(x) 已经满足大部分对日期设置的要求了。

    Quartz.Net官方2.X教程  http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/index.html

    Quartz.Net开源地址   https://github.com/quartznet/quartznet

     

     

  • 相关阅读:
    jenkins+docker+rancher+zikui 部署
    利用jenkins直接构件docker镜像并发布到docker服务器
    docker+Rancher+K3S
    windows使用VSCode进行Shell开发
    v-drag 弹框拖拽的实现
    vue3兄弟组件传值
    vue3 组件传值
    Azure Computer Vision 之 Smart Crop 智能裁剪图片
    ASP.NET Core 单元测试
    ASP.NET Core Static Files
  • 原文地址:https://www.cnblogs.com/qqhewei/p/14236825.html
Copyright © 2011-2022 走看看