Quartz.Net 定时任务框架

时间:2022-10-11 07:49:40

Quartz.Net是一个从java版的Quartz移植过来的定时任务框架,可以实现异常灵活的定时任务,开发人员只要编写少量的代码就可以实现“每隔1小时执行”,“每天22点执行”,

“每月18日的下午执行8次”等各种定时任务。

Quartz.Net的基本概念:

Quartz.Net中的概念:计划者(IScheduler),工作(IJob),触发器(Trigger)。

总结是就是:给计划者一个工作,让它在Trigger(什么条件下做这件事)触发的条件下执行这个工作(IJob)

将要定时执行的任务的代码写到实现IJob 接口的Execute 方法中即可,时间到来的时候Execute方法会被调用。


使用方法:

安装Quartz.Net    (因为版本变化太大,前后可能不兼容,因此这边建议安装 2.5.0版本)

去Nuget程序包中搜索Quartz.net安装,或者执行:  Install-Package Quartz -Version 2.5.0

Install-Package Quartz -Version 2.5.0

Quartz.Net 定时任务框架

第一步:在项目中创建一个类(我取名叫MyQuartz),这个类继承自Quartz.Net 的IJob接口 

using System;

namespace MvcApp
{
    using Quartz;
    using System.IO;
    using System.Web.Hosting;

    /// <summary>
    /// 创建一个定时任务执行任务的MyQuartz类,这个类必须继承自IJob
    /// </summary>
    public class MyQuartz : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            //注意点:比如我设置了一年每月都执行一次任务代码,那遇到春节不需要执行怎么办呢?难道春节的时候要把项目停下来修改下代码,然后再发布? 答案是当然不需要。该怎么执行依然怎么执行,我们只需要在这里设置一下就可以了
            //例如在Execute方法的最上面做一个判断:如果当前月是春节,直接return。哈哈,是不是很灵活

            try
            {
                //我们需要定时任务执行的代码都写在这个Execute方法里          
                File.AppendAllText("d://a.txt", "*****" + DateTime.Now.ToString() + "******");

                //注意点1:使用Quartz执行定时任务的时候,有个容易出错的点,就是在我们使用HttpContext类
                //当我们HttpContext.Current.Server.MapPath("~/Web.Config") 来获取某个文件的物理路径的时候
                //容易报空引用这个错误,因为使用Quartz执行定时任务的时候Execute方法是在单独的线程中被执行的
                //而我们的这个HttpContext.Current只能在外部的处理线程中我们才能用,所以它为null。所以就报空引用了

                //那这个问题我们怎么解决呢?我们可以用另外一个类来替代
                //var path = HostingEnvironment.MapPath("~/Web.Config");

                //注意点2
                //IJob的Execute中异常问题:由于Job是运行在单独的线程中的,以你次如果Execute中如果发生异常,调试的时候也不会断点暂停的,就好像什么也没有发生过一样,如果运行在Asp.net中,也不会触发Asp.net的“未处理异常处理程序”就好像没有执行一样。为了当出现异常的时候我们能及时发现,就需要把Execute的代码用try..Catch包裹起来。然后把异常处理(比如记录到日志)
                

            }
            catch (Exception ex)
            {
                File.AppendAllText("d://log.txt", "程序报错啦:" + ex.Message);
            }

        }
    }
}

第二布:配置

我选择在MVC项目的App_Start文件夹中创建一个QuartzConfig.cs类,将配置文件写在这里(你们可以选择你们觉得合适的地方,只要能执行到这个配置文件代码就行)

using System;
namespace MvcApp.App_Start
{
    using Quartz;
    using Quartz.Impl;
    using Quartz.Spi;
    public class QuartzConfig
    {
        public static void RunProgramRunExample()
        {
            //创建一个任务的安排者(调度者)
            IScheduler sched = new StdSchedulerFactory().GetScheduler();


            //--------------任务1

            //创建一个任务,
            //第一个参数:表示任务名称,我这里取名叫“RenWuNameA”,它必须是唯一的
            //第二个参数:表示需要定时执行任务的这个类的类名(这个类必须实现了IJob接口的)
            JobDetailImpl jbBossReport = new JobDetailImpl("RenWuNameA", typeof(MyQuartz));


            //创建一个任务的执行条件(Trigger)例如:在什么时候执行这个任务,在几点几时执行这个任务。
            //AtHourAndMinuteOnGivenDaysOfWeek 表示每天执行
            //我这里设置在每天的的23:45分执行
            //第一个参数:表示小时
            //第二个参数:表示分钟
            IMutableTrigger triggerBossReport =
                CronScheduleBuilder.DailyAtHourAndMinute(0, 47).Build();//表示在每天的23:45分执行

            /*
            //AtHourAndMinuteOnGivenDaysOfWeek 表示在可多选的周几周几执行(可多选)
            //我这里设置在每周六和每周日的13:55分执行
            //第一个参数:表示小时
            //第二个参数:表示分钟
            //第三个参数:是一个可变数组,是一个DayOfWeek类型的枚举,可选周一,周二,周三,周四,周五,周六,周日)
            var triggerBossReport2 =
            CronScheduleBuilder.AtHourAndMinuteOnGivenDaysOfWeek(13, 55, DayOfWeek.Saturday, DayOfWeek.Sunday).Build();

            */

            /*
            //WeeklyOnDayAndHourAndMinute表示每周固定时间执行:
            //我这里设置每周五的10:25分执行
            //第一个参数:是一个DayOfWeek类型的枚举,可选周一,周二,周三,周四,周五,周六,周日
            //第二个参数:小时
            //第三个参数:分钟
            var triggerBossReport3 =
            CronScheduleBuilder.WeeklyOnDayAndHourAndMinute(DayOfWeek.Friday, 10, 25).Build();
            */

            /*
            //MonthlyOnDayAndHourAndMinute表示每月月固定时间执行
            //我这里设置每月的第25天的9:30 分执行
            var triggerBossReport4 =
            CronScheduleBuilder.MonthlyOnDayAndHourAndMinute(25, 9, 30);
            */

            /*
            //这里我设置每3秒执行一次
            CalendarIntervalScheduleBuilder builder = CalendarIntervalScheduleBuilder.Create();
            //WithInterval方法有2个参数
            //第二个参数:表示时间刻度,如年,月,周,日,时,分,秒,毫秒(它是一个枚举)
            //第一个参数:表示根据第二个参数选择的时间刻度,执行的次数
            builder.WithInterval(3, IntervalUnit.Second);
            var triggerBossReport = builder.Build();
            */

            /*
             //我们还可以使用cron表达式来指定时间执行。
             //了解cron表达式:http://www.cnblogs.com/junrong624/p/4239517.html
             //"0 0 10,14,16 * * ?"就是表达式,表示每天上午10点,下午2点,下午4点执行
             var triggerBossReport5 =
             CronScheduleBuilder.CronSchedule("0 0 10,14,16 * * ?").Build();
             */


            //表示每隔5秒执行一次
            //"*/5 * * * * ?" 表达式就表示每隔五秒执行一次
            //var triggerBossReport = CronScheduleBuilder.CronSchedule("*/5 * * * * ?").Build();


            //设置这个执行条件的Key。我这里将它取名为triggerTest,名字要保证唯一
            triggerBossReport.Key = new TriggerKey("triggerTest");

            //将给定的“任务”添加到调度程序中,并关联给定的“执行条件”
            sched.ScheduleJob(jbBossReport, triggerBossReport);




            //------------------任务2
            JobDetailImpl jR2 = new JobDetailImpl("RenWuNameB", typeof(MyQuartz));
            var tBR2 = CronScheduleBuilder.AtHourAndMinuteOnGivenDaysOfWeek(13, 55, DayOfWeek.Saturday, DayOfWeek.Sunday).Build();
            tBR2.Key = new TriggerKey("tT2");
            sched.ScheduleJob(jR2, tBR2);


            //启动
            sched.Start();

        }

    }
}

配置好后,我们在程序启动的时候调用它,所以我选择了在Global.asax中调用执行这个配置文件

namespace MvcApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            //调用定时任务
            QuartzConfig.RunProgramRunExample();
        }
    }
}