您现在的位置是:网站首页> 编程资料编程资料

作业调度框架Quartz.net用法详解_实用技巧_

2023-05-24 250人已围观

简介 作业调度框架Quartz.net用法详解_实用技巧_

一、介绍

Quartz.NET是一个强大、开源、轻量的作业调度框架,你能够用它来为执行一个作业而创建简单的或复杂的作业调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等。在2017年的最后一天Quartz.NET 3.0发布,正式支持了.NET Core 和async/await。这是一个大版本,有众多新特性和大的功能

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

源码:https://github.com/quartznet/quartznet

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

新功能

  • 支持 async/await 基于任务的作业,内部以async/await工作
  • 支持.NET Core / netstandard 2.0和.NET Framework 4.5.2及更高版本
  • 通过提供程序名称SQLite-Microsoft支持Microsoft.Data.Sqlite,旧的提供程序SQLite也仍然有效,还可以用
  • 增加了对SQL Server内存优化表的初步支持和Quartz.Impl.AdoJobStore.UpdateLockRowSemaphoreMOT
  • 从依赖关系中删除Common.Logging
  • 删除C5 Collections,使用.NET框架内置的Collections
  • 在插件启动时添加对作业调度XML文件的验证
  • 在TimeZoneUtil中添加对额外自定义时区解析器功能的支持

Quartz3.x和2.x最大的优势在于:支持异步执行Job,所以建议将Job的Excute方法设计为异步方法,这样做可以提高任务调度和执行效率。

quartz的构成和基本工作流程

在使用Quart.net前,我们先理解下quartz的构成和基本工作流程,

1、Quartz包含以下五个基本部分:

  • Scheduler 调度器,quartz工作时的独立容器
  • Trigger 触发器,定义了调度任务的时间规则
  • Job 调度的任务
  • ThreadPool 线程池(不是clr中的线程池),任务最终交给线程池中的线程执行
  • JobStore RAWStore和DbStore两种,job和trigger都存放在JobStore中

2、Quartz的基本工作流程

scheduler是quartz的独立运行容器,trigger和job都可以注册在scheduler容器中。

其中trigger是触发器,用于定义调度任务的时间规则,job是被调度的任务,一个job可以有多个触发器,而一个触发器只能属于一个job。

Quartz中一个调度线程QuartzSchedulerThread,调度线程可以找到将要被触发的trigger,通过trigger找到要执行的job,然后在ThreadPool中获取一个线程来执行这个job。

JobStore主要作用是存放job和trigger的信息。

二、基于文件配置

Quartz.NET 在3.x已经将插件分离了,所以如果要从xml直接加载文件,需要引入插件包

1、引入包

2、配置

app.config

******************************Plugin配置*********************************************

quartz_jobs.xml

 This file contains job definitions in schema version 2.0 format true 开始执行一个调度 jldwjobkelun计量单位 格式:实现了IJob接口的包含完整命名空间的类名,程序集名称 truefalsejlwdkelunjldwjobkelun 2018-01-22T00:00:00+08:00 每3秒执行一次 

3、接口实现

using Kelun.Log4Net; using Quartz; using System.Reflection; using System.Threading.Tasks; namespace Kelun { class JldwJob : IJob { private static readonly IMyLog Logger = MyLogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public Task Execute(IJobExecutionContext context) { return Task.Run(() => { Logger.Info("定时任务执行"); }); } } }

4、启动Quartz

public MainForm() { InitializeComponent(); RunProgramAsync().GetAwaiter().GetResult(); } private static async Task RunProgramAsync() { try { StdSchedulerFactory factory = new StdSchedulerFactory(); IScheduler scheduler = await factory.GetScheduler(); //开启调度器 await scheduler.Start(); //创建一个作业 //IJobDetail job = JobBuilder.Create().WithIdentity("myJob", "group1").Build(); //ITrigger trigger = TriggerBuilder.Create() // .WithIdentity("myTrigger", "group1") // .StartNow() //现在开始 // .WithSimpleSchedule(x => x // .WithIntervalInSeconds(1) //触发时间,1秒一次 // .RepeatForever()) // .Build(); //把作业,触发器加入调度器。 //await scheduler.ScheduleJob(job, trigger); //await scheduler.Shutdown(); } catch (SchedulerException se) { Logger.Error("执行错误", se); } }

5、禁用Quartz.NET日志输出

6、当应用或网站关闭时结束正在执行的工作

在Global.asax中的Application_End方法中添加如下代码:

 protected void Application_End(object sender, EventArgs e) { // 在应用程序关闭时运行的代码 if (scheduler != null) { scheduler.Shutdown(true); } }

三、基于代码的方式

用五分钟看一个简单的例子吧,这个例子中通过调度器工厂StdSchedulerFactory获取一个调度器实例scheduler,然后定义Job和trigger,并注册到调度器中,最后启动scheduler就可以执行我们的任务了。代码如下:

using Quartz; using Quartz.Impl; using System; using System.Threading.Tasks; namespace ConsoleApp3 { internal class Program { private static void Main(string[] args) { //调度器,生成实例的时候线程已经开启了,不过是在等待状态 StdSchedulerFactory factory = new StdSchedulerFactory(); IScheduler scheduler = factory.GetScheduler().Result; //创建一个Job,绑定MyJob IJobDetail job = JobBuilder.Create() //获取JobBuilder .WithIdentity("jobname1", "group1") //添加Job的名字和分组 .WithDescription("一个简单的任务") //添加描述 .Build(); //生成IJobDetail //创建一个触发器 ITrigger trigger = TriggerBuilder.Create() //获取TriggerBuilder .StartAt(DateBuilder.TodayAt(01, 00, 00)) //开始时间,今天的1点(hh,mm,ss),可使用StartNow() .ForJob(job) //将触发器关联给指定的job .WithPriority(10) //优先级,当触发时间一样时,优先级大的触发器先执行 .WithIdentity("tname1", "group1") //添加触发器的名字和分组 .WithSimpleSchedule(x => x.WithIntervalInSeconds(1) //调度,一秒执行一次,执行三次 .WithRepeatCount(3) .Build()) .Build(); //start让调度线程启动【调度线程可以从jobstore中获取快要执行的trigger,然后获取trigger关联的job,执行job】 scheduler.Start(); //将job和trigger注册到scheduler中 scheduler.ScheduleJob(job, trigger).Wait(); Console.ReadKey(); } } #region MyJob /// /// 一个简单的Job,所有的Job都要实现IJob接口 /// public class MyJob : IJob { public async Task Execute(IJobExecutionContext context) { await Task.Run(() => { Console.WriteLine("hello quartz!"); //JobDetail的key就是job的分组和job的名字 Console.WriteLine($"JobDetail的组和名字:{context.JobDetail.Key}"); Console.WriteLine(); }); } } #endregion MyJob }

通过Quartz来调度一个任务十分简单,执行结果如下:

四、Quartz.net的概念和基本用法

1.TriggerBuilder介绍

在Quartz中Trigger的作用是定义Job何时执行。

Quartz.net提供了四种触发策略:SimpleSchedule,CalendarIntervalSchedule,DailyTimeIntervalSchedule和CronSchedule。

TriggerBuilder顾名思义就是用来创建Trigger的。

1、SimpleSchedule

Simpleschedule 是最简单的一种触发策略,它的作用类似于timer,可以设置间隔几秒/几分钟/几小时执行一次,如创建一秒执行一次的触发器如下

ITrigger trigger = TriggerBuilder.Create() .StartNow() .Wit
                
                

-六神源码网