QuartzNet的基本使用,Scheduler,Job,Trigger的应用

news2024/11/26 5:27:10

Quartz.Net的基本使用方法

Quartz.Net的基本使用是比较简单的,主要是对下面三个工具的创建和使用。

  1. Scheduler调度器
  2. Job执行的动作
  3. Trigger触发器

Scheduler的创建和使用

scheduler的创建有几种不同的方式,但一般可以直接使用其提供的工厂类直接创建

  • 通过工厂类创建-----像StdSchedulerFactory和DirectSchedulerFactory
   /*StdFactory是用到最多的情况,亦可以通过NameValueCollection读取不同形式的键值对参数(.prop,.txt应该都可以),其创建的Scheduler即为StdScheduler类型*/
   StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

   IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

   /*directfatory和stdfactory有很多区别,一般可以用于更细节的Custom,
     1. directfactory为单例设计
     2. directfactory可以通过CreateScheduler(args)自定scheduler 
     3. directfactory无法通过键值对获取初始属性 */
   DirectSchedulerFactory directSchedulerFactory = DirectSchedulerFactory.Instance;


   directSchedulerFactory.CreateScheduler(new DefaultThreadPool(), new RAMJobStore());

   IScheduler scheduler2 = await directSchedulerFactory.GetScheduler();

  • 绑定Job和Trigger
    在scheduler里绑定对应的Job和Trigger,然后调用Start()开始即可。
     static async Task Main(string[] args)
    {
        StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

        IScheduler scheduler = await stdSchedulerFactory.GetScheduler();
        //这里先直接使用builder创建trigger,在后面再详细的解释(PS:withRepeateCount的实际执行次数为count+1)
        ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();

        //创建一个简单的Job,一般的Job都有很多的参数,这里先用无参的方法替代一下。
        IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("JOB:one").Build();

        await scheduler.ScheduleJob(job, trigger);

        await scheduler.Start();

        //停主线程--查看效果
        Thread.Sleep(7000);
        
    }

    public class SimpleJob : IJob

    {
        public async Task Execute(IJobExecutionContext context)
        {
            Console.WriteLine("Hello QuartZnet!");
        }
    }

在这里插入图片描述

Job的创建和参数的传递

只要实现IJob接口的类就可以称之为Job类,
IJob接口只有Execute(IJobExecutionContext context)方法
其context为上下文参数,保存着IJob执行过程的信息,
也保存着需要的参数。
方法体则为具体的定时业务

Job的传参方式

Job的传参方式为通过JobDetail的JobDataMap进行键值对存取。


static async Task Main(string[] args)
{
    StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

    IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

    ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();

    IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("JOB:one").Build();

    //在键值对中添加参数
    job.JobDataMap.Add("UserName", "小明");
    job.JobDataMap.Add("Pets", new List<string>() { "小狗","小猫","乌龟","仓鼠" });

    await scheduler.ScheduleJob(job, trigger);
    await scheduler.Start();

    Thread.Sleep(7000);
    
}


public class SimpleJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        Console.WriteLine("Hello QuartZnet!");
        //再context上下文中获取参数[也可以获取执行的其他信息]
        string argOne = (string)context.JobDetail.JobDataMap.Get("UserName");
        List<string> argTwo = (List<string>)context.JobDetail.JobDataMap.Get("Pets");

        Console.WriteLine(argOne);
        argTwo.ForEach(item => { Console.WriteLine(item); });

    }
}

PS: 不要在Job类中添加自定义的构造函数,因为JobBuilder是无法使用DI(依赖注入)配置Job的,故无法使用构造函数传参

Job的ID设置

当你需要创建不确定量的任务时,你需要设置Job的ID不唯一。即:
不能多个scheduler启动一个相同ID的Job.

错误例:

StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
//假设有两个调度器,
IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

IScheduler scheduler2 = await stdSchedulerFactory.GetScheduler();

ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();

IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("ThisOne").Build();


job.JobDataMap.Add("UserName", "小明");
job.JobDataMap.Add("Pets", new List<string>() { "小狗","小猫","乌龟","仓鼠" });

await scheduler.ScheduleJob(job, trigger);
;
await scheduler.Start();

//ObjectAlreadyExistsException,
//Unable to store Job: 'DEFAULT.ThisOne', because one already exists with this identification.'
//这里的异常即为JobID已经存在(或者说是重复)
await scheduler2.ScheduleJob(job, trigger);

await scheduler2.Start();

Thread.Sleep(7000);

在这里插入图片描述

ID重复的解决方法
  1. 设置不同的ID(trigger也需要设置)

//本测试在Main方法中,故直接创建不同的Job/Trigger对象使用不同的ID即可
//如果你提供方法/API来创建任务,推荐使用:
//UUID,数据库生成ID
//来保证不重复
IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

IScheduler scheduler2 = await stdSchedulerFactory.GetScheduler();

ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();

ITrigger trigger2 = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerTwo").Build();


IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("ThisOne").Build();

IJobDetail job2 = JobBuilder.Create<SimpleJob>().WithIdentity("ThisTwo").Build();


job.JobDataMap.Add("UserName", "小明");
job.JobDataMap.Add("Pets", new List<string>() { "小狗","小猫","乌龟","仓鼠" });

job2.JobDataMap.Add("UserName", "小明");
job2.JobDataMap.Add("Pets", new List<string>() { "小狗", "小猫", "乌龟", "仓鼠" });

await scheduler.ScheduleJob(job, trigger);

await scheduler.Start();

await scheduler2.ScheduleJob(job2, trigger2);

await scheduler2.Start();

Thread.Sleep(7000);
  1. UnScheduleJob(trigger);解绑Trigger和Job

通过UnScheduleJob可以解绑trigger和Job
可以在任何时候解绑
但也有着不同的效果

  • Start后立马解绑------Job不会被执行
StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

//假设有两个调度器,
IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();


IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("ThisOne").Build();

job.JobDataMap.Add("UserName", "小明");
job.JobDataMap.Add("Pets", new List<string>() { "小狗","小猫","乌龟","仓鼠" });


await scheduler.ScheduleJob(job, trigger);

await scheduler.Start();

await scheduler.UnscheduleJob(new TriggerKey("TriggerOne"));

Thread.Sleep(6000);

执行效果:
在这里插入图片描述

  • schedule执行完毕后解绑-------同一Job和Trigger可以在解绑后再绑定其他schedule

      StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
    
      //假设有两个调度器,
      IScheduler scheduler = await stdSchedulerFactory.GetScheduler();
    
      IScheduler scheduler2 = await stdSchedulerFactory.GetScheduler();
    
      ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(action => { action.WithIntervalInSeconds(2).WithRepeatCount(1); }).WithIdentity("TriggerOne").Build();
    
      
      IJobDetail job = JobBuilder.Create<SimpleJob>().WithIdentity("ThisOne").Build();
    
      
      job.JobDataMap.Add("UserName", "小明");
      job.JobDataMap.Add("Pets", new List<string>() { "小狗","小猫","乌龟","仓鼠" });
    
      
      await scheduler.ScheduleJob(job, trigger);
    
      await scheduler.Start();
    
      Thread.Sleep(6000);
      //等待执行完成后解绑job和trigger
      bool isCompleted = scheduler.GetTriggerState(new TriggerKey("TriggerOne")).IsCompleted;
      if(isCompleted)
          await scheduler.UnscheduleJob(new TriggerKey("TriggerOne"));
    
      //再绑定新的scheduler,则可以正常运行了
      await scheduler2.ScheduleJob(job, trigger);
    
      await scheduler2.Start();
    
      Thread.Sleep(7000);
    

对比

  1. 创建新ID的Job和Trigger
    Job/Trigger间彼此独立,可以在同一时间创造多个任务,但是可能线程开销会比较大
  2. 解绑Job和Trigger于scheduler,重复使用Job和Trigger
    同一个Job可重复使用,可能可以节省开销,
    但是如果解绑的时间可能和任务的执行时间造成冲突,导致任务无法执行

Trigger的创建和使用

Trigger为Job的触发器,通过TriggerBuilder进行创建

在QuartZ中,提供了4类现成的生成Trigger类型的方法

  1. WithSimpleSchedule
  2. WithDailyTimeIntervalSchedule
  3. WithCalendarIntervalSchedule
  4. WithCronSchedule

每一种方法都对应一些方面的安排

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

安排Trigger执行的开始/结束时间

可以通过StartAt和StartNow来控制开始时间
反之EndAt可以控制结束的时间。

static async Task Main(string[] args)
{
    StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

    //假设有两个调度器,
    IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

    //简单触发器
    ITrigger simpleTrigger = TriggerBuilder.Create().WithSimpleSchedule(option => {
        option.WithIntervalInSeconds(1);    //可以设置间隔时间
        option.WithRepeatCount(999);        //也可以设置重复次数
    })
        .StartAt(DateTime.Now.AddSeconds(5))          //可以设置哎固定的区间内
        .EndAt(DateTime.Now.AddSeconds(15)).Build();

    IJobDetail jobDetail = JobBuilder.Create<SimpleJob>().WithIdentity("JobOne").Build();

    await scheduler.ScheduleJob(jobDetail,simpleTrigger);

    await scheduler.Start();

    Thread.Sleep(15000);

}

public class SimpleJob : IJob
{

    public async Task Execute(IJobExecutionContext context)
    {
        Console.WriteLine(DateTime.Now);
    }
}

请添加图片描述

使用Cron表达式安排任务

CronTrigger的使用更加简单,只需要cron表达式作为参数即可,如果需要了解可以看下图

请添加图片描述

请添加图片描述

也有很多在线工具提供Cron表达式的生成

https://freeformatter.com/cron-expression-generator-quartz.html

例:

static async Task Main(string[] args)
{
    StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();

    IScheduler scheduler = await stdSchedulerFactory.GetScheduler();

    //Cron表达式无法直接控制重复次数,但可以通过EndAt方法间接调节
    ITrigger Crontrigger = TriggerBuilder.Create().WithCronSchedule("0/2 * * * * ?").StartAt(DateTime.Now.AddSeconds(5)).Build();

    IJobDetail jobDetail = JobBuilder.Create<SimpleJob>().WithIdentity("JobOne").Build();

    await scheduler.ScheduleJob(jobDetail, Crontrigger);

    await scheduler.Start();

    Thread.Sleep(15000);

}

public class SimpleJob : IJob
{

    public async Task Execute(IJobExecutionContext context)
    {
        Console.WriteLine(DateTime.Now);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享92个NET源码,总有一款适合您

NET源码 分享92个NET源码&#xff0c;总有一款适合您 92个NET源码下载链接&#xff1a;https://pan.baidu.com/s/1Ya4GMXuHhNbqkLU5b7SPEw?pwd5vpx 提取码&#xff1a;5vpx 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&…

【指针面试题】-还在为学过指针的理论只是不会实践吗??赶紧来看看这里讲解了许多指针的面试题,带你更好掌握指针!!!

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f9e8;作者宣言&#xff1a;认真写好每一篇博客 &#x1f38a;作者gitee:link &#x1f389;指针笔试题详解&#x1f4a5;前言&#x1f4a6;一、指针和数组面试题解析&#x1f4a8;1.1一维数组&#x1f4a2;1.2字…

Episode 01 密码技术基础

一、加密和解密&&发送者、接收者和窃听者 发送者&#xff1a;发出消息的人 接收者&#xff1a;接收消息的人 窃听者&#xff1a;恶意获取消息的第三方 加密&#xff1a;发送者将明文转换为密文 解密&#xff1a;接收者将密文还原为明文 破译&#xff1a;接收者以外…

客流统计系统为什么深受门店商户的喜爱?

人数或人群流动信息进行精确的统计分析&#xff0c;而且还可以利用这些高精度的数据&#xff0c;还能获得该区域精确的客流量信息&#xff0c;实现有效合理的组织运营工作&#xff0c;提升工作效益&#xff0c;帮助使用者开展更有成效的组织工作。客流统计系统内置高性能CMOS图…

同源跨域的概念与实现跨域的几种方案

本文将结合周老师的讲义对同源与跨域这一前端经典问题进行系统的总结、整理。一起来坐牢&#xff0c;快&#xff01; 1. 同源限制 1.1 历史背景 - 含义的转变 1995年&#xff0c;同源政策由 Netscape 公司引入浏览器。目前&#xff0c;所有浏览器都实行这个政策。 最初&…

【无标题】javaEE初阶---多线程(面试常用)

这篇文章 , 我将主要介绍多线程进阶部分的内容 . 主要涉及到一些在面试中常考的内容。 一:常见的锁策略 1.1乐观锁和悲观锁 乐观锁 : 预测接下来发生锁冲突的可能性不大 , 而进行的一类操作; 悲观锁 : 预测接下来发生锁冲突的可能性很大 , 而进行的一类操作.乐观锁 : 假设数…

ClassIn:如何打造更稳定的Zabbix监控系统

作者简介&#xff1a;罗呈祥。现就职于北京翼鸥教育科技有限公司&#xff0c;负责数据库相关的运维管理和技术支持工作&#xff0c;擅长故障处理和性能优化&#xff0c;对分布式数据库也有深入研究。 近期&#xff0c;OceanBase 社区发布了一篇关于我们公司选型分布式数据库的文…

bilateral_filter 双边滤波器详细用法

一、双边滤波&#xff08;Bilateral filter&#xff09;是一种可以保边去噪的滤波器。其输出像素的值依赖于邻域像素的值的加权组合。 从效果来说&#xff0c;双边滤波可产生类似美肤的效果。皮肤上的皱纹和斑&#xff0c;与正常皮肤的差异&#xff0c;远小于黑白眼珠之间的差异…

13种Shell逻辑与算术,能写出5种算你赢!

相较于最初的 Bourne shell&#xff0c;现代 bash 版本的最大改进之一体现在算术方面。早期的 shell 版本没有内建的算术功能&#xff0c;哪怕是给变量加1&#xff0c;也得调用单独的程序来完成。 1、算术方法一&#xff1a; $(( )) 只要都是整数运算&#xff0c;就可以在 $(…

DHT11温湿度传感器初识

目录 一、产品概述 1、接线方式 2、特点 3、数据传送逻辑 二、发送时序检测模块是否存在 1、C51单片机&#xff08;主机&#xff09;时序分析 2、编写代码检测模块是否存在 3、读取DHT11数据的时序分析 三、温湿度通过串口传到PC显示 四、温湿度检测小系统——使数据…

Discrete Opinion Tree Induction for Aspect-based Sentiment Analysis 论文阅读笔记

一、作者 Chenhua Chen、Zhiyang Teng、Zhongqing Wang、Yue Zhang School of Engineering, Westlake University, China Institute of Advanced Technology, Westlake Institute for Advanced Study Soochow University 二、背景 如何为每一个方面词定位相应的意见上下文…

反补码运算之 “1 - 1 = - 1 ” ?

我们在研究数据的二进制表示时遇到这样一个问题&#xff1a; 由于计算中的CPU只有加法器&#xff0c;没有减法器&#xff0c;所以在计算机采用原码做减法时对于&#xff1a;1 - 1 0 相当于1 &#xff08;-1&#xff09;&#xff0c;用二进制表示为&#xff1a;000110011001。…

儿童感染新冠病毒后发高烧如何应对?专家来支招

儿童感染新冠病毒后发热较多&#xff0c;但肺炎发展较少儿童感染新冠病毒后发高烧&#xff0c;是重症吗&#xff1f;徐红梅&#xff1a;从目前的接待情况来看&#xff0c;儿童感染新冠病毒后比成人发烧。超过一半的儿童在感染后有发烧症状&#xff0c;伴有咳嗽、鼻塞、流鼻涕、…

JavaWeb的一些学习总结

Web系统就是&#xff1a;前端负责貌美如花&#xff0c;后端负责坚如磐石 企业在做Web系统时&#xff0c;成本与收益的对比是不可忽视的&#xff0c;企业做项目一定是要盈利的&#xff01; 企业做项目最求的不是技术的新和潮&#xff0c;追求的是低成本和稳还有好用度&#xff…

函数的设计

一、默认参数 C允许在函数定义或声明时&#xff0c;为形参指定默认值&#xff0c;即默认参数&#xff08;default argument&#xff09;。 &#xff08;1&#xff09;函数定义与函数声明只能设置一次默认参数。 &#xff08;2&#xff09;可以设置多个默认参数&#xff0c;设…

【精华】搞定JVM调优学习

JVM 介绍 1. 什么是 JVM JVM 是 Java Virtual Machine&#xff08;Java 虚拟机&#xff09;的缩写。一台执行 Java 程序的机器。 2 .JAVA 语言的执行原理 计算机语言&#xff1a; 计算机能够直接执行的指令。这种指令和系统及硬件有关。 计算机高级语言&#xff1a; 在遵循…

「数据」驱动行业拐点,毫末智行冲刺自动驾驶3.0时代

“毫末预计&#xff0c;到2025年中国高阶辅助驾驶搭载率将达到70%。而在汽车新消费领域&#xff0c;中国汽车市场增换购消费比例将达到60%&#xff0c;智能驾驶功能成为必选因素&#xff0c;并迎来商业化的加速发展。”1月5日&#xff0c;第七届HAOMO AI DAY上&#xff0c;毫末…

黑马学ElasticSearch(五)

目录&#xff1a; &#xff08;1&#xff09;DSL查询语法-DSL查询分类和基本语法 &#xff08;2&#xff09;DSL查询语法-全文检索查询 &#xff08;3&#xff09;DSL查询语法-精确查询 &#xff08;4&#xff09;DSL查询语法-地理查询 &#xff08;5&#xff09;DSL查询语…

计算机网络(一)

计算机网络1 概述1.1 计算机网络的作用1.2 因特网概述1.2.1 网络的网络1.2.2 Internet和internet的区别1.2.3 因特网发展的三个阶段1.2.4 ISP介绍1.2.5 ISP分类1.2.5.1 主干ISP1.2.5.2 地区ISP1.2.5.3 本地ISP1.2.6 因特网交换点 IXP1.3 因特网的组成1.3.1 因特网的边缘部分1.3…

资产管理4大难点,如何破解?

随着企业业务扩大、人员增多&#xff0c;固定资产的数量和种类也会随着增加。此时&#xff0c;如何高效管理企业资产就成为很多企业亟待解决的一大难题。 传统资产管理4大难点 01.资产管理部门需要联系采购部门、使用部门、财务部门等收集数据&#xff0c;汇总难且工作量大&…