c# 版本的Quartz.net定时调度器

Quartz.net是一个功能比Timer强大的定时调度类库(C#)。网上大多是Java的Quartz教程,所以这里稍微记录下C#的Quartz.net。

Quaartz.net: DLL包下载地址(我自己上传的):https://download.csdn.net/download/qq_42354598/10597312

说明:调度器:IScheduer       作业:IJobDetail       触发器:ITrigger(类)

一个IScheduer可以调度多个Job,一个job能由多个ITrigger触发,但一个ITrigger只能触发一个Job。触发器定义时是和Job绑定在一起的。(次数主要用CRON调度表达式,特别强大)

cron在线生成器:http://cron.qqe2.com/

Quartz.net 程序包下载地址:

1.可以用VS的NUGet程序包管理器下载:下载命令:Install-Package Quartz

2.百度貌似找不到(官网也不能下),我是去CSDN下载的,比较全

 

//注意:下载的类库一定是Quartz.net(C#版本的)。Java版本的Quartz在这用不了(方法名略有差异)
Using Quartz;
Using Quartz.impl;

class A
{
    public A(){}
    public void  AnExample(){
      //1.先创建一个调度器实例
    IScheduer isched=new StdScheduerFacktory().getScheduer();

       //2.利用IJobDetail创建IJob(作业)

    IJobDetail job1 = JobBuilder.Create().WithIdentity("job1").Build();
       //传递参数的方法可以用
       //①.UsingJobdata("参数")   这里只能传递数字和字符串.创建Job时也可以不传参数
       //②job1.JobDataMap["name1"]=任何对象   存储对象后,JobDataMap是以Object类型存储的,取 
      //出来时要类型转换一下。Job1Class是一个类,job1与其Execute()方法绑定,job1触发时自动执行
     //job1Class下的Execute()方法与job1自动绑定。
IJobDetail job1=JobBuilder.create().withIdentify("job1","group1").UsingJobData("这里是字符串").UsingJobData(
3.14).Build();
        //3.创建与job1绑定的触发器。触发器的触发规则我用的是CRON表达式
ITrigger trigger1=TriggerBuilder.create().withIdentify("name1","group").withCronTrigger("Cron表达式").forJob(job1.key).startNow().Build();
       //4.在调度器isched注册job1和trigger1
isched.ScheduerJob(job1,trigger1);


//同理可以创建多个job和与job对应的触发器,在调度器注册之。

    }  
1

注意:withIdentity()有3中:

1.withIdentity(jobkey或trigkey)   2.withIdentity(“name1”,“group1”)    3.withIdentity("name1")

//其中对key来说

Jobkey jkey=new Jobkey("name123")  //输出jkey.toString() :Default.name123

Jobkey jkey2=new Jobkey("name111","group1111")//同理:name111,group111

TriggerKey tkey = new TriggerKey("trigger2");输出tkey.toString(): Default.trigger2

TriggerKey tkey = new TriggerKey("trigger222",“group987”);//同理:trigger222,group987
 
class job1Class:IJob
{
    public job1Class(){}
    public virture void Execute(IJobExecuteContext context){
        //获取传递进来的参数
        JobDataMap dataMap=context.IJobDetail.JobDataMap;

        //get(“xx”),getString("xx"),getFloat("xx")
        //取出之前创建JOB时传过来的参数。任何参数存进JobDataMap都会转化为Object类型,取出时要强制类型转换一下
        DataTable DT=(DataTable)dataMap.get("参数名");
        //注意:jobKey job1key=context.IJobDetail.key和triggerKey可以获取身份标识

       //接下来用取得的参数执行你想要的的作业了

    }

}

//测试结论:工厂通过getScheduler()得到的都是同一个调度器(得到的调度器对象均指向一个默认的实例)
//查:怎么创建带名字的不同的调度器?           
//job和trigger的身份标识有3个重载             
//在调度器里的job之间或trigger之间不能重名
//

public void asdf()
        {

            string cron1 = "0/5 * * * * ? *"; //每隔5秒触发器触发一次job.
            //调度器q
            IScheduler q = new StdSchedulerFactory().GetScheduler();
            IJobDetail job1 = JobBuilder.Create().WithIdentity("job1").Build();
            ITrigger trigger1 = TriggerBuilder.Create().WithIdentity("trigger1").WithCronSchedule(cron1).ForJob(job1.Key).StartNow().Build();
            q.ScheduleJob(job1, trigger1);


            //调度器a
            IScheduler a = new StdSchedulerFactory().GetScheduler();
            IJobDetail job_1 = JobBuilder.Create().WithIdentity("job1").Build();
            ITrigger trigger_2 = TriggerBuilder.Create().WithIdentity("trigger2").WithCronSchedule(cron1).ForJob(job_1.Key).StartNow().Build();
                
            //这里发生异常:Quartzxxx...xxx 调度器里已经存在名为job1的作业和trigger1的调度器了
            a.ScheduleJob(job_1, trigger_1);
        }






//通过jobdataMap可以传递任何类型的参数到ceshi类下的Execute方法
//ceshi类(随便建的一个测试类)必须实现IJob接口和该接口的Execute方法)
        public void qwer()
        {
            IScheduler q = new StdSchedulerFactory().GetScheduler();
            string cron1 = "0/5 * * * * ? *";
            string cron2 = "0/10 * * * * ? *";
            string cron3 = "0/20 * * * * ? *";
            IJobDetail job1 = JobBuilder.Create().WithIdentity("job1").Build();
            job1.JobDataMap["job1"] = "job1111";
            IJobDetail job2 = JobBuilder.Create().WithIdentity("job2").Build();
            job2.JobDataMap["job2"] = "job2222";
            IJobDetail job3 = JobBuilder.Create().WithIdentity("job3").Build();
            job3.JobDataMap["job3"] = "job3333";

            ITrigger trigger1 = TriggerBuilder.Create().WithIdentity("trigger1").WithCronSchedule(cron1).ForJob(job1.Key).StartNow().Build();
            ITrigger trigger2 = TriggerBuilder.Create().WithIdentity("trigger2").WithCronSchedule(cron2).ForJob(job2.Key).StartNow().Build();
            ITrigger trigger3 = TriggerBuilder.Create().WithIdentity("trigger3").WithCronSchedule(cron3).ForJob(job3.Key).StartNow().Build();

            q.ScheduleJob(job1, trigger1);
            q.ScheduleJob(job2, trigger2);
            q.ScheduleJob(job3, trigger3);
            if (q.IsShutdown)
            {
                MessageBox.Show("1");
            }
            if (!q.IsStarted)
                MessageBox.Show("2");
            q.Start();  //启动调度器
        }


//终止任务并删除(移除任务时,必须先获得该job和trigger的身份key)
//这里的例子大都是一个触发器对应一个job
        public void deleteJob()
        {
            IScheduler isched = new StdSchedulerFactory().GetScheduler();
            JobKey jkey = new JobKey("job2");
            TriggerKey tkey = new TriggerKey("trigger2");
            isched.PauseTrigger(tkey);  //停止触发器
            isched.UnscheduleJob(tkey); //移除触发器
            isched.DeleteJob(jkey);     //删除作业
        }

针对方法:asdf()和qwer(),创建作业job时传递进去的ceshi类,意在:当trigger触发job时,job会自动执行ceshi类下的Execute方法。。但是ceshi类必须实现IJob接口和该接口的方法public virture void Execute(IJobExecuteContext context)。

注意:为什么要用JobDataMap传递参数,而不用ceshi类的构造对象啊,函数啊传递呢?

因为Job每次触发去执行Execute()时,都会新建一个ceshi类的对象,用该对象去执行Execute()。。。。所以最好用一个新的类实现IJob,不要在Job所在的类写Execute() (如果这时候刚好你在构造对象里做复杂的事,每次生成对象执行execute都会做很多无用的事,搞不好死循环)

//获取传递进来的参数:get(“xx”),getString("xx"),getFloat("xx")
//取出之前创建JOB时传过来的参数。任何参数存进JobDataMap都会转化为Object类型,取出时要强制类型转换一下成原来的类型
class ceshi:IJob
{
    public virture void Execute(IJobExecuteContext context){
         //  jobKey job1key=context.IJobDetail.key和triggerKey可以获取身份标识 
       
               
        JobDataMap dataMap=context.IJobDetail.JobDataMap; 
        string name1=(string)dataMap.get("job1");
        string name2=(string)dataMap.get("job2");
        string name3=(string)dataMap.get("job3");
        //  DataTable DT=(DataTable)dataMap.get("参数名");
        //  string str=(string)dataMap.get("参数名");
        if(name1="job1111") 
           console.writeLine("job1执行"); 
        if(name2="job2222") 
           console.writeLine("job2执行");  
        if(name3="job3333") 
           console.writeLine("job3执行");      
              
    }

结果是每隔5秒输出:job1执行。每隔10秒输出:job2执行。每隔20秒输出:job3执行

我用了3个job,去调用ceshi类。所以在Execute要区分一i下不同的job。可以获得jobkey去区分。

jobKey job1key=context.IJobDetail.key 

if(job.toString()=="name1,group1")

if(job.toString()=="Default.name11")

如果每一个JOB都有对应的一个execute类,那就不用区分了

更多详细可以参考:

后记:触发器的触发情况:用cron,比较强大。其他的一般般

           还在继续完善中

你可能感兴趣的:(C#)