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是经过许多大项 ...
随机推荐
- iframe中,重新加载页面
比如在iframe中的页面,设置一个onclick事件的触发函数flush function flush(){ window.location.reload(); }
- vs调试,监控变量
- curl库pycurl实例及参数详解
pycurl是功能强大的python的url库,是用c语言写的,速度很快,比urllib和httplib都快. 今天我们来看一下pycurl的用法及参数详解 常用方法: pycurl.Curl() # ...
- Spring学习九----------Bean的配置之Bean的定义及作用域的注解实现
© 版权声明:本文为博主原创文章,转载请注明出处 Spring Bean常用注解 @Component:通常注解,可用于任何Bean @Repository:通常用于注解DAO层,即持久层 @Serv ...
- c++引用返回值
引用作为函数的返回值时,函数的返回值能够理解为函数返回了一个变量(事实上,函数返回引用时,它返回的是一个指向返回值的隐式指针),因此,值为引用的函数能够用作赋值运算符的左操作数.另外,用引用返回一个函 ...
- Excel COM组件使用的注意事项和一些权限问题(转载)
1.实例化Excel的COM组件的时候,不要直接调用类,要用Microsoft提供的接口 原来的写法:Excel.ApplicationClass excelApp = new Excel.Appli ...
- 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- 【WPF学习笔记】[转]周银辉之WPF中的动画 && 晓风影天之wpf动画——new PropertyPath属性链
(一)WPF中的动画 动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式 ...
- 将web工程部署到tomcat
http://blog.csdn.net/lucklq/article/details/7621807 http://jingyan.baidu.com/article/466506582f2f4af ...
- Android使用ViewPager实现无限循环滑动及轮播(附源代码)
MainActivity例如以下: package cc.ww; import java.util.ArrayList; import android.app.Activity; import and ...