C# quartz.net 定时任务(一)

4 篇文章 1 订阅

quartz是Java里面非常普遍的定时任务框架,

asp.net里面对应的是quartz.net,版本最新的3.2.3(项目是.net framwork 4.7)

官网:https://www.quartz-scheduler.net/

quick-start:https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html

内容分三节~

目录

 

安装

主要成员

Job

Trigger

Scheduler

Scheduler简介

框架核心接口

Job和JobDetail

Job

Trigger

JobDataMap

Job上可以加上注解

Job的其他属性

JobExecutionException

 


 

安装

nuget控制台

install-package quartz

主要成员

Job

Job是具体的业务逻辑所在,是定时任务中要执行的那一项任务    

Trigger

Trigger触发器,规定了定时任务的执行时间、频率、次数

Scheduler

Scheduler调度器将Job和Trigger关联起来,负责整个定时任务的开启、关闭

示例

class Program
    {
        public static async Task Main(string[] args)
        {
            ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
            IScheduler scheduler=await schedulerFactory.GetScheduler();//创建scheduler
            await scheduler.Start();//启动scheduler

            IJobDetail job = JobBuilder.Create<TestJob>()
                .WithIdentity("testJob", "testGroup")
                .Build();//创建job(jobdetail)

            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("testTrigger", "testGroup")
                .StartNow()
                .WithSimpleSchedule(x=>x.WithIntervalInSeconds(10).RepeatForever())
                .Build();//创建trigger 现在开始 每10秒执行一次  无限重复

            await scheduler.ScheduleJob(job, trigger);//scheduler关联trigger和job
            Console.ReadLine();
        }
    }

    public class TestJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {//定时job的执行内容
            await Task.Run(()=>{ 
                Debug.WriteLine("testJob");
            });
        }
    }

Scheduler简介

要使用Scheduler不能直接new这个对象,要使用ISchedulerFactory的实现类(工厂)来创建Schedule

I开头这个很显然是接口

官方提供了实现类StdSchedulerFactory

实例化一个Scheduler以后,Scheduler可以:

Start:开始定时任务,定时触发任务执行

待机:暂停,触发器也不会启动

Shutdown:停止调度器,不会在定时触发执行任务

这里既然专门提到ISchedulerFactory接口,那么我们自己也可以实现这个接口!(TODO:暂时没有应用ISchedulerFactory的需求)

 

框架核心接口

  • IScheduler  操作Scheduler的核心api
  • IJob  业务逻辑所在地!要实现接口的Excute方法
  • IJobDetail  用来实例化Job的!
  • ITrigger  一个job可以对应多个trigger,但是一个trigger只能对应一个job!所有trigger都实现该接口。
  • JobBuilder  用来创建JobDetail实例(JobDetail再创建Job实例)
  • TriggerBuilder  用来创建Trigger实例。而且我们可以看到示例代码中的方法级联(流式接口)
  • SchedulerBuilder  用来创建Scheduler实例

 

Job和JobDetail

Job

定时任务只需要继承IJob就可以了,然后必须要实现Execute方法

public class TestJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            await Task.Run(()=>{ 
                Debug.WriteLine("testJob");
            });
        }
    }

Execute方法里面的内容,就是定时任务要执行的业务逻辑!官方建议不要给Job类加属性,因为每次任务会新建一个Job(数据无法通过属性从这次传递到下次)

当Job关联的Trigger触发的时候,Job的Execute方法就会执行:

Trigger触发的时候,关联的JobDetail加载,相关的TestJob通过Scheduler关联的JobFactory创建TestJob实例,获取JobDataMap数据,调用TestJob的Execute方法。

 

参数JobExecutionContext是Job运行时的环境相关的数据:包括Job关联的Scheduler、Trigger(当前触发的Trigger)、JobDetail还有其他参数

JobDetail是Job被加入到Scheduler里面的时候创建的,

我们发现示例代码上,实际上使用JobBuilder创建了一个IJobDetail类型的实例,而不是直接创建Job实例。

每当Scheduler执行任务时,会在TestJob的Execute方法执行前创建一个新的TestJob实例,

第一次和第二次定时执行的任务是两个不同的TestJob实例!

实际上官方提到Job实例的时候,一般指的是JobDetail,而实现了IJob的TestJob,被称为任务类型(Job Type)

具体之后再说。

Trigger

Trigger可以包含JobDataMap参数,最常用的Trigger是

1. SimpleTrigger  (实现ISimpleTrigger接口)包含常用的方法,常用的定时任务大都可以实现

2. CronTrigger  (实现ICronTrigger接口) 主要是可以使用Cron表达式,来实现复杂的触发方式(当然简单的也可以)

Job和Trigger可以用WithIdentity方法来指定JobKey/TriggerKey    和  groups  方便把任务和触发器分组,同一个组内不能重名!


JobDataMap

IJobDetail有一个JobDataMap属性,可以用来往Job里面传参。

JobDataMap实现了IDictionary接口,这里官方建议只传基本类型和string类型的参数

quartz已经封装好了方法,方便我们再实例化IJobDetail的时候设置JobDataMap参数,然后再Job的Execute方法里面获取JobDataMap参数。

分别是

设置参数:IJobDetail的UsingJobData

获取参数:IJobExecutionContext的JobDetail.JobDataMap属性的GetString(GetInt等等)方法

示例代码如下:

 class Program
    {
        public static async Task Main(string[] args)
        {
            ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
            IScheduler scheduler=await schedulerFactory.GetScheduler();
            await scheduler.Start();

            IJobDetail job = JobBuilder.Create<TestJob>()
                .WithIdentity("testJob", "testGroup")
                .UsingJobData("stringParam","hello job")
                .UsingJobData("numberParam",2020)
                .Build();

            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("testTrigger", "testGroup")
                .StartNow()
                .WithSimpleSchedule(x=>x.WithIntervalInSeconds(10).RepeatForever())
                .Build();

            await scheduler.ScheduleJob(job, trigger);
            Console.ReadLine();
        }
    }

    public class TestJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            JobDataMap jobParam= context.JobDetail.JobDataMap;
            string paramStr= jobParam.GetString("stringParam");
            int paramNo = jobParam.GetInt("numberParam");
            await Console.Out.WriteLineAsync("paramStr=" + paramStr + ",paramNo=" + paramNo);
        }
    }

Trigger也可以使用UsingJobData,使用场景是:

多个Trigger来触发同一个Job,不同的Trigger需要传不同的参数

示例代码如下

class Program
    {
        public static async Task Main(string[] args)
        {
            ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
            IScheduler scheduler=await schedulerFactory.GetScheduler();
            await scheduler.Start();

            IJobDetail job = JobBuilder.Create<TestJob>()
                .WithIdentity("testJob", "testGroup")
                .Build();

            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("testTrigger", "testGroup")
                .UsingJobData("stringParam", "hello trigger")
                .UsingJobData("numberParam", 2021)
                .StartNow()
                .WithSimpleSchedule(x=>x.WithIntervalInSeconds(10).RepeatForever())
                .Build();

            await scheduler.ScheduleJob(job, trigger);
            Console.ReadLine();
        }
    }

    public class TestJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            JobKey key = context.JobDetail.Key;//测试获取JobDetail的JobKey(JobBuilder设置的)
            JobDataMap jobParam = context.MergedJobDataMap;//获取Trigger设置的JobDataMap
            string paramStr= jobParam.GetString("stringParam");
            int paramNo = jobParam.GetInt("numberParam");
            await Console.Out.WriteLineAsync("key="+key+",paramStr=" + paramStr + ",paramNo=" + paramNo);
            //key=testGroup.testJob,paramStr=hello trigger,paramNo=2021
        }
    }

Job上可以加上注解

TestJob上可以加下面两种注解

[DisallowConcurrentExecution] :不能并发执行一个TestJob的多个实例

[PersistJobDataAfterExecution]:如果JobDataMap里面的数据修改了,下次执行TestJob的Execute方法的时候,使用的JobDataMap数据是上次调用时修改过的!

如果使用PersistJobDataAfterExecution注解,请配合DisallowConcurrentExecution一起使用,否则出现数据共享,容易出错

Job的其他属性

Durability:没有任何激活的Trigger和Job关联的时候,Job会被自动从Scheduler中删除掉

RequestsRecovery:如果job执行过程中,电脑死机了or服务器被强关了等等,设置属性可以让Scheduler重新start的时候,job重新执行!设置成功的话JobExecutionContext.Recovering属性将会是true(用来检测)

具体写法是JobBuilder.Create<TestJob>().RequestRecovery(true) // 不手动设置的话默认是false

JobExecutionException

IJob.Execute()方法中的代码块,永远都要用try catch 来处理,捕获的异常都是JobExecutionException

可以在quartz的api上查看这个类的很多属性和方法,例如:e.RefireImmediately = true; 可以立刻重新执行任务

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值