Quartz.Net初探
想必大家在工作中经常会遇到这样类似的需求,在某个时间或者需要不间断的执行某个业务动作去满足任务需求。例如,我们写了一个job,定时去处理一些任务,在没有了解到Quartz.Net之前,我是这样做的,进行轮询处理,如图:

是不是感觉很low啊。前些日子,了解到了Quartz.Net,它是一个强大的开源任务调度器,它提供的触发器以及Cron表达式能够很好的满足我们在日常开发中遇到的定时服务的工作处理,为了在以后工作中更好的使用它,我对它的基本使用方法进行了整理,当然下面所讲到的只是它的一些常用功能,至于更强大的功能,例如远程调度等等,还需要后续再进一步了解。但是在我看来,已能够满足我们在日常中的大部分开发工作。
1、建立如下解决方案,如图:

正如大家看到的,我在解决方案中添加了QuartzTest的控制台项目进行demo演示,需要说明的是,大家可通过Nuget将Quartz包添加至项目当中。根据Quartz的常用操作,整理出了 BaseJob以及QuartzHelper帮助类。
BaseJob类中包含了要执行任务的基本信息,例如Job名称,组名,触发器名称,执行间隔时间等等信息,在实现具体Job时,只要继承该基类并使用相应的构造函数对Job基本信息进行初始化即可。
如下图:

QuartzHelper中对常用的任务调度方法进行了整理,这里我们将TestJob添加至调度器并开始任务的执行,如下图:

该Demo以及整理的完整代码如下:
/// <summary>
/// 任务基类
/// </summary>
public abstract class BaseJob : IJob
{
private string _jobName = string.Empty;
private string _gropName = string.Empty;
private string _triggerName = string.Empty;
private int _intervalTime;
private DateTimeOffset _startTime;
private DateTimeOffset? _endTime;
private int _repeatCount;
private string _cronExpression; /// <summary>
/// 无参构造函数
/// </summary>
public BaseJob()
{ } /// <summary>
/// 构造函数
/// </summary>
/// <param name="jobName">任务名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="gropName">任务组名称</param>
/// <param name="intervalTime">间隔时间</param>
public BaseJob(string jobName, string triggerName, string gropName, int intervalTime)
{
this._jobName = jobName;
this._triggerName = triggerName;
this._gropName = gropName;
this._intervalTime = intervalTime;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="jobName">任务名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="gropName">任务组名称</param>
/// <param name="intervalTime">间隔时间</param>
/// <param name="cronExpression">cron表达式</param>
public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, string cronExpression)
{
this._jobName = jobName;
this._triggerName = triggerName;
this._gropName = gropName;
this._intervalTime = intervalTime;
this._cronExpression = cronExpression;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="jobName">任务名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="gropName">任务组名称</param>
/// <param name="intervalTime">间隔时间</param>
/// <param name="startTime">开始时间</param>
/// <param name="endTime">结束时间</param>
public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, DateTimeOffset startTime, DateTimeOffset? endTime)
{
this._jobName = jobName;
this._triggerName = triggerName;
this._gropName = gropName;
this._intervalTime = intervalTime;
this._startTime = startTime;
this._endTime = endTime;
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="jobName">任务名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="gropName">任务组名称</param>
/// <param name="intervalTime">间隔时间</param>
/// <param name="startTime">开始时间</param>
/// <param name="endTime">结束时间</param>
/// <param name="repeatCount">重复次数</param>
public BaseJob(string jobName, string triggerName, string gropName, int intervalTime, DateTimeOffset startTime, DateTimeOffset? endTime, int repeatCount)
{
this._jobName = jobName;
this._triggerName = triggerName;
this._gropName = gropName;
this._intervalTime = intervalTime;
this._startTime = startTime;
this._endTime = endTime;
this._repeatCount = repeatCount;
} /// <summary>
/// 任务名称
/// </summary>
public string JobName
{
get { return _jobName; }
set { _jobName = value; }
} /// <summary>
/// 触发器名称
/// </summary>
public string TriggerName
{
get { return _triggerName; }
set { _triggerName = value; }
} /// <summary>
/// 任务组名称
/// </summary>
public string GropName
{
get { return _gropName; }
set { _gropName = value; }
} /// <summary>
/// 执行间隔时间
/// </summary>
public int IntervalTime
{
get { return _intervalTime; }
set { _intervalTime = value; }
} /// <summary>
/// 开始时间
/// </summary>
public DateTimeOffset StartTime
{
get { return _startTime; }
set
{
if (value == null || value == DateTime.MinValue) _startTime = SystemTime.UtcNow();
else _startTime = value;
}
} /// <summary>
/// 结束时间
/// </summary>
public DateTimeOffset? EndTime
{
get { return _endTime; }
set { _endTime = value; }
} /// <summary>
/// 重复执行次数
/// </summary>
public int RepeatCount
{
get { return _repeatCount; }
set { _repeatCount = value; }
} /// <summary>
/// Cron表达式
/// </summary>
public string CronExpression
{
get { return _cronExpression; }
set { _cronExpression = value; }
} /// <summary>
/// 任务执行
/// </summary>
/// <param name="context">任务执行上下文</param>
public abstract void Execute(IJobExecutionContext context);
}
/// <summary>
/// Quartz帮助类
/// </summary>
public class QuartzHelper
{
private static ISchedulerFactory _schedulerFactory;
private static IScheduler _scheduler; /// <summary>
/// 构造函数
/// </summary>
static QuartzHelper()
{
_schedulerFactory = CreateSchedulerFactory();
_scheduler = GetScheduler();
} #region 获取服务器使用的调度程序
/// <summary>
/// 获取服务器使用的调度程序。
/// </summary>
/// <returns></returns>
protected static IScheduler GetScheduler()
{
return _schedulerFactory.GetScheduler();
}
#endregion #region 创建调度器工厂
/// <summary>
/// 创建调度器工厂。
/// </summary>
/// <returns></returns>
protected static ISchedulerFactory CreateSchedulerFactory()
{
return new StdSchedulerFactory();
}
#endregion #region 委托调度器,启动实例
/// <summary>
/// 委托调度器,启动实例。
/// </summary>
public static void Start()
{
try
{
_scheduler.Start();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 委托调度器,停止实例
/// <summary>
/// 委托调度器,停止实例。
/// </summary>
public static void Stop()
{
try
{
if (!_scheduler.IsShutdown)
_scheduler.Shutdown(true);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 暂停调度器中所有的活动
/// <summary>
/// 暂停调度器中所有的活动。
/// </summary>
public static void Pause()
{
try
{
_scheduler.PauseAll();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 恢复所有活动
/// <summary>
/// 恢复所有活动。
/// </summary>
public static void Resume()
{
try
{
_scheduler.ResumeAll();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 添加任务(任务间隔时间单位:小时)
/// <summary>
/// 添加任务(任务间隔时间单位:小时)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForHours<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
.WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 添加任务(任务间隔时间单位:分钟)
/// <summary>
/// 添加任务(任务间隔时间单位:分钟)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForMinutes<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
.WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 添加任务(任务间隔时间单位:秒)
/// <summary>
/// 添加任务(任务间隔时间单位:秒)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForSeconds<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:小时)
/// <summary>
/// 根据开始以及结束时间进行添加任务(任务间隔时间单位:小时)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForHoursStartEndTime<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:分钟)
/// <summary>
/// 根据开始以及结束时间进行添加任务(任务间隔时间单位:分钟)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForMinutesStartEndTime<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间进行添加任务(任务间隔时间单位:秒)
/// <summary>
/// 根据开始以及结束时间添加任务(任务间隔时间单位:秒)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForSecondsStartEndTime<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).RepeatForever())
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:小时)
/// <summary>
/// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:小时)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForHoursRepeatCount<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInHours(job.IntervalTime).WithRepeatCount(job.RepeatCount))
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:分钟)
/// <summary>
/// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:分钟)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForMinutesRepeatCount<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInMinutes(job.IntervalTime).WithRepeatCount(job.RepeatCount))
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:秒)
/// <summary>
/// 根据开始以及结束时间执行指定重复次数进行添加任务(任务间隔时间单位:秒)
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForSecondsRepeatCount<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build();
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithIdentity(job.TriggerName, job.GropName).StartAt(job.StartTime).EndAt(job.EndTime)
.WithSimpleSchedule(x => x.WithIntervalInSeconds(job.IntervalTime).WithRepeatCount(job.RepeatCount))
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion #region 通过Cron表达式添加任务
/// <summary>
/// 通过Cron表达式添加任务
/// </summary>
/// <typeparam name="T">具体任务</typeparam>
public static void AddJobForCron<T>()
where T : BaseJob, new()
{
try
{
T job = new T();
IJobDetail jobDetail = JobBuilder.Create<T>().WithIdentity(job.JobName, job.GropName).Build(); ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.WithIdentity(job.TriggerName, job.GropName)
.WithCronSchedule(job.CronExpression)
.Build();
_scheduler.ScheduleJob(jobDetail, trigger);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
}
/// <summary>
/// 测试 job
/// </summary>
public class TestJob : BaseJob
{
public TestJob() : base("TestJob", "TestTrigger", "TestGrop",) { }
public override void Execute(IJobExecutionContext context)
{
try
{
Console.WriteLine(string.Format("当前任务执行时间:{0}", DateTime.Now.ToString()));
Thread.Sleep(TimeSpan.FromSeconds());
}
catch (Exception ex)
{
throw ex;
}
}
}
class Program
{
static void Main(string[] args)
{
QuartzHelper.AddJobForSeconds<TestJob>();
QuartzHelper.Start();
}
}
2、运行解决方案,得到如下结果:

发现是不是任务按照我们所希望的那样运行了,但是大家有没有注意到,TestJob中 有这样一句代码: Thread.Sleep(TimeSpan.FromSeconds(3));
任务是Sleep3秒钟的,可是我们的Job却一直在执行呢,即使上一次任务还没执行完,它又开始执行了。在我们的实际开发中,我们需要一次任务执行完成后再执行下一次任务。
我们对TestJob 进行改造,代码如下:
/// <summary>
/// 测试 job
/// </summary>
[DisallowConcurrentExecution]
public class TestJob : BaseJob
{
public TestJob() : base("TestJob", "TestTrigger", "TestGrop",) { }
public override void Execute(IJobExecutionContext context)
{
try
{
Console.WriteLine(string.Format("当前任务执行时间:{0}", DateTime.Now.ToString()));
Thread.Sleep(TimeSpan.FromSeconds());
}
catch (Exception ex)
{
throw ex;
}
}
}
再次运行,如图:

大家发现区别没呢,没错,我们在TestJob类上添加了“DisallowConcurrentExecution”特性,这样,就能在一次任务执行完成后,再进行下次任务的执行了。
Quartz.Net初探的更多相关文章
- Quartz.Net 学习之路02 初探Quartz.Net
第二讲:简单的实例,看看Quartz.Net强在哪里? 直接上代码,代码里有注释: using System; using Quartz; using Quartz.Impl; namespace L ...
- Quartz每次调度时被执行两次
[关键字:重复执行.重复调用.每次执行两次.执行2次] 前言: 先说一下,项目背景.由于组内某成员在用Maven搭建项目时不规范,导致项目的名称与实际访问项目名称不一致.在部署项目时,必需要配一下虚拟 ...
- 免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)
很多的软件项目中都会使用到定时任务.定时轮询数据库同步,定时邮件通知等功能..NET Framework具有“内置”定时器功能,通过System.Timers.Timer类.在使用Timer类需要面对 ...
- Quartz
Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中.它提供了巨大的灵 活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度. eg: ja ...
- Spring Quartz实现任务调度
任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维 ...
- 初探领域驱动设计(2)Repository在DDD中的应用
概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...
- topshelf和quartz内部分享
阅读目录: 介绍 基础用法 调试及安装 可选配置 多实例支持及相关资料 quartz.net 上月在公司内部的一次分享,现把PPT及部分交流内容整理成博客. 介绍 topshelf是创建windows ...
- CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探
CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...
- Quartz.net持久化与集群部署开发详解
序言 我前边有几篇文章有介绍过quartz的基本使用语法与类库.但是他的执行计划都是被写在本地的xml文件中.无法做集群部署,我让它看起来脆弱不堪,那是我的罪过. 但是quart.net是经过许多大项 ...
随机推荐
- Centos7 安装 Maven 3.5.*
下载 Apache Maven 访问 Maven官方网站,打开后找到下载链接,如下: 解压 tar zxvf apache-maven-3.5.3-bin.tar.gz 添加环境变量 打开 /etc/ ...
- php的strip_tags,htmlspecialchars,htmlentities,stripslashes,addslashes解释
php函数蛮多的,要完整的每个函数都理解深刻是个挺有挑战性的事情. strip_tags,htmlspecialchars,htmlentities,stripslashes,addslashes这几 ...
- Rider
听说你开发.NET还在用VS,小哥哥给你推荐全平台的Rider 本文地址:http://www.cnblogs.com/likeli/p/8461010.html 前言 .NET平台的开发一直都只 ...
- 网页图表类框架(插件)——百度eCharts和Highcharts
ECharts, 缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库, 可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9 /10 ...
- 进程间通信(IPC)+进程加锁解锁
[0]README 0.1) source code and text description are from orange's implemention of a os: 0.2) for com ...
- Python—发邮件总结
来自: http://my.oschina.net/jhao104/blog/613774 1.登录SMTP服务器 首先使用网上的方法(这里使用163邮箱,smtp.163.com是smtp服务器地址 ...
- Nodejs学习笔记 --- 调用命令方法ld_process.exec()和child_process.execFile()
本文主要记录项目中使用NodeJS实现在线构建项目时,通过代码自动调用命令行. 参考资料&内容来源: Nodejs官网:http://nodejs.cn/api/child_process.h ...
- ideal 快捷键
1.输入sout --> System.out.println(); 2.输入psvm --> main函数; IntelliJ Idea 2017 免费激活方法 1. 到网站 http: ...
- Linux就该这么学--了解Shell脚本
有人曾经将Shell形容是人与计算机硬件的“翻译官”,Shell作为用户与Linux系统通讯的媒介.自身也定义了各种变量和参数,并提供了诸如循环.分支等高级语言才有的控制结构特性.如何正确的使用这些功 ...
- crm高速开发之EntityCollection
/* 创建者:菜刀居士的博客 * 创建日期:2014年07月07号 */ namespace Net.CRM.OrganizationService { using System; ...