Quartz.NET开源库实现作业定时调度——常用示例_xiaochenXIHUA的博客-CSDN博客
Quartz.NET作业定时任务调度简单示例工程下载
一、Quartz.NET简介 1.1、.NET Framework自带的Timer定时器介绍很多的软件项目中都会使用到定时任务、定时轮询数据库同步,定时邮件通知等功能。.NET Framework具有“内置”定时器功能,通过System.Timers.Timer类实现。
自带定时器的缺点:
①在使用Timer类需要面对的问题:计时器没有持久化机制;
②计时器具有不灵活的计划(仅能设置开始时间和重复间隔,没有基于日期,时间等);
③计时器不使用线程池(每个定时器一个线程);计时器没有真正的管理方案 - 你必须编写自己的机制,以便能够记住,组织和检索任务的名称等。
1.2、Quartz.NET介绍Quartz.NET是一个强大、开源、轻量的作业调度框架,可以与任何其他软件系统集成或一起使用。作业调度程序是一个系统,负责在执行预处理程序时执行(或通知)其他软件组件 - 确定(调度)时间到达。Quartz是非常灵活的,并且包含多个使用范例,可以单独使用或一起使用,以实现您所需的行为,并使您能够以您的项目看起来最“自然”的方式编写代码。
Quartz.NET优点:
①组件的使用非常轻便,并且需要非常少的设置/配置,如果您的需求相对基础,它实际上可以使用“开箱即用。
②是容错的,并且可以在系统重新启动之间保留(记住)您的预定作业。
③能够用它来为执行一个作业而创建简单的或复杂的作业调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等。非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等。
Quartz是作为一个小的动态链接库(.dll文件)分发的,它包含所有的核心Quartz功能。 此功能的主要接口(API)是调度程序接口。 它提供简单的操作,如调度/非调度作业,启动/停止/暂停调度程序。如果你想安排你自己的软件组件执行,他们必须实现简单的Job接口,它包含方法execute()。 如果希望在计划的触发时间到达时通知组件,则组件应实现TriggerListener或JobListener接口。主要的Quartz'进程'可以在您自己的应用程序或独立应用程序(使用远程接口)中启动和运行。
1.3、Quarzt.NET的官方地址官网:http://www.quartz-scheduler.net/
源码:https://github.com/quartznet/quartznet
示例:Quartz.NET Quick Start Guide | Quartz.NET (quartz-scheduler.net)
Quartz.NET是 OpenSymphony 的 Quartz API 的.NET移植,用C#改写,可用于winform和Web应用中。它灵活而不复杂,你能够用它来为执行一个作业而创建简单的或复杂的作业调度。Quartz.NET 3.0 已经开始支持 .NET Core/.NET Standard 2.0。
Job 为作业的接口,JobDetail 用来描述 Job 的实现类及其它相关的静态信息;Trigger 作为作业的定时管理工具。
一个 Trigger 只能对应一个作业实例,而一个作业实例可对应多个 Trigger ;
Scheduler 做为定时任务容器,它包含了所有触发器和作业,每个 Scheduler 都存有 JobDetail 和 Trigger的注册,一个 Scheduler 中可以注册多个 JobDetail 和多个 Trigger 。
二、实现步骤 2.1、安装Quartz.NET包 2.2、创建一个简单的定时任务示例这里实现一个定时执行方法输出执行时间的示例
1、编写需要定时执行的方法,必须继承【IJob】
using Quartz;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace TestQuartz.FixedTimeTask
{
class TimeJob : IJob
{
///
/// 作业调度定时执行的方法
///
///
///
public async Task Execute(IJobExecutionContext context)
{
string str = $"{this.GetType().Name} 方法执行,执行时间是:{DateTime.Now} ID:{context.FireInstanceId}" +Environment.NewLine;
await Console.Out.WriteLineAsync(str);
}
}//Class_end
}
2、要定时执行这个方法,你需要先用【IJobDetail】接口绑定该方法,然后再使用【ITrriger】接口监听,接着使用【StdSchedulerFactory】调度工厂实例化【IScheduler】调度器接口启动;
//1、使用IJobDetail 接口绑定需要定时执行的方法【TimeJob】 IJobDetail job = JobBuilder.Create() .WithIdentity("job1", "group1") .Build(); // 2、使用ITrriger监听器每10秒重复监听 ITrigger trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(10) .RepeatForever()) .Build(); // 3、通知调度器用定义好的监听器执行该绑定的方法 await scheduler.ScheduleJob(job, trigger); // 注意:你也可以让调度器使用多个监听器监听同一个方法 // await scheduler.ScheduleJob(job, new List () { trigger1, trigger2 }, replace: true);
3、确定任务执行的时间间隔
//任务执行的时间间隔(可自定义,比如这里的是10秒) await Task.Delay(TimeSpan.FromSeconds(10));
4、还可以添加日志记录,不过当没有任何日志接口对接时,该日志则不进行记录。
//日志类需要继承ILogProvider接口
private class ConsoleLogProvider : ILogProvider
{
public Logger GetLogger(string name)
{
return (level, func, exception, parameters) =>
{
if (level >= LogLevel.Info && func != null)
{
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
}
return true;
};
}
public IDisposable OpenNestedContext(string message)
{
throw new NotImplementedException();
}
public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
{
throw new NotImplementedException();
}
}
//调用方法
LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
2.3、完整的调用示例
using System;
using System.Threading.Tasks;
using Quartz;
using Quartz.Impl;
using Quartz.Logging;
namespace QuartzSampleApp
{
public class Program
{
private static async Task Main(string[] args)
{
LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
// Grab the Scheduler instance from the Factory
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
// and start it off
await scheduler.Start();
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create()
.WithIdentity("job1", "group1")
.Build();
// Trigger the job to run now, and then repeat every 10 seconds
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.RepeatForever())
.Build();
// Tell quartz to schedule the job using our trigger
await scheduler.ScheduleJob(job, trigger);
// some sleep to show what's happening
await Task.Delay(TimeSpan.FromSeconds(60));
// and last shut down the scheduler when you are ready to close your program
await scheduler.Shutdown();
Console.WriteLine("Press any key to close the application");
Console.ReadKey();
}
// simple log provider to get something to the console
private class ConsoleLogProvider : ILogProvider
{
public Logger GetLogger(string name)
{
return (level, func, exception, parameters) =>
{
if (level >= LogLevel.Info && func != null)
{
Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
}
return true;
};
}
public IDisposable OpenNestedContext(string message)
{
throw new NotImplementedException();
}
public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
{
throw new NotImplementedException();
}
}
}
public class TimeJob: IJob
{
public async Task Execute(IJobExecutionContext context)
{
string str = $"{this.GetType().Name} 方法执行,执行时间是:{DateTime.Now} ID:{context.FireInstanceId}" +Environment.NewLine;
await Console.Out.WriteLineAsync(str);
}
}
}
三、封装好了一个简易的单个任务调度器
3.1、单个定时任务调度器的核心
using Quartz;
using Quartz.Impl;
using Quartz.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace FixedTimeTask
{
class SingleTaskScheduler
{
#region 基础参数
//调度工厂
private static StdSchedulerFactory _factory;
//调度器
private static IScheduler _scheduler;
//详细任务
private IJobDetail _job;
//触发器
private ITrigger _trigger;
//触发的时间间隔
private int _trrigerInterval = 5;
//任务执行的时间间隔
private int _taskRunInterval = 20;
//执行次数
private uint _runNumber = 0;
#endregion
///
/// 构造函数
///
/// 任务执行的时间间隔
/// 触发器的时间间隔
public SingleTaskScheduler(int taskRunInterval,int trrigerInterval)
{
_taskRunInterval = taskRunInterval;
_trrigerInterval = trrigerInterval;
}
#region 公有方法
///
/// 启动定时方法
///
///
public async Task StartFiexedTimeMethod()where T:IJob
{
Console.WriteLine("开始调用定时任务!!!");
//创建日志
LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
//从调度工厂获取调度器实例
_factory = new StdSchedulerFactory();
_scheduler = await _factory.GetScheduler();
//启动实例
await _scheduler.Start();
//绑定定时执行方法
BindFiexedTimeMethod();
//创建定时执行的触发器
CreateFiexedTimeTrigger(_trrigerInterval);
//告诉quartz用我们的触发器安排任务
await _scheduler.ScheduleJob(_job,_trigger);
//任务执行的时间间隔
await Task.Delay(TimeSpan.FromSeconds(_taskRunInterval));
Console.WriteLine("------------执行完成一轮定时任务----------");
}
///
/// 关闭定时方法
///
/// 返回关闭结果
public bool CloseFiexedTimeMethod()
{
Task task=_scheduler?.Shutdown();
return task.IsCompletedSuccessfully;
}
#endregion
#region 私有方法
///
/// 绑定定时方法
///
private void BindFiexedTimeMethod()where T:IJob
{
_job = JobBuilder.Create()
//.WithIdentity("时间任务1", "组1")
.Build();
}
///
/// 创建定时执行触发器
///
///
private void CreateFiexedTimeTrigger(int seconds)
{
if (seconds < 0) return;
_trigger = TriggerBuilder.Create()
//.WithIdentity("时间任务触发器1", "组1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(seconds)
.RepeatForever())
.Build();
}
#endregion
}//Class_end
}
3.2、单定时任务调度器使用方法
//1-引用命名空间 using FixedTimeTask; //2-实例化单定时任务调度器(可以自由定义:任务执行的时间间隔、与触发器执行的时间间隔) SingleTaskScheduler taskScheduler = new SingleTaskScheduler(10,5); //3-启动定时方法 await taskScheduler.StartFiexedTimeMethod四、其他使用Quartz.NET的参考(); //4-最后可以关闭定时方法 bool success = taskScheduler.CloseFiexedTimeMethod();
详解免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)_实用技巧_脚本之家 (jb51.net)



