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是经过许多大项 ...
随机推荐
- Ubuntu下载、zsync、安装、常见问题
下载-镜像地址 http://mirrors.ustc.edu.cn/ubuntu-releases/ http://mirrors.163.com/ubuntu-releases/ Ubuntu 更 ...
- VueJS路由
Vue.js 路由 本章节我们将为大家介绍 Vue.js 路由. Vue.js 路由允许我们通过不同的 URL 访问不同的内容. 通过 Vue.js 可以实现多视图的单页Web应用(single pa ...
- WPF实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中“全选”时,列表中所有的项目都会被选中 ...
- 自定义一个处理图片的HttpHandler
有时项目里我们必须将图片进行一定的操作,例如水印,下载等,为了方便和管理我们可以自定义一个HttpHander 来负责这些工作 后台: public class ImageHandler : IHtt ...
- WCP人员管理之添加人员
1.用户管理页面 其中 : var url_formActionUser = "user/form.do";//增加.修改.查看URL 2. 通过 /form 路由, 转到 Use ...
- 搭建SVN服务器详细教程
搭建SVN服务器详细教程 本教程会从最基本的下载安装到上传代码,下载代码这条线来详细讲述如何完成SVN服务器的搭建 下载并安装VisualSVN server 下载并安装TortoiseSVN 导入项 ...
- css 字体的unicode码
微软雅黑: YaHei宋体: SimSun黑体: SimHei ;
- Grunt学习笔记【8】---- grunt-angular-templates插件详解
本文主要讲如何用Grunt打包AngularJS的模板HTML. 一 说明 AngularJS中使用单独HTML模板文件的地方非常多,例如:自定义指令.ng-include.templateUrl等. ...
- SAP流水号
[转]编号范围对象维护 Tcode: SNRO OYSM 1.Number Range的通用Tcode:SNRO 2.Number Range的通用读取函数:NUMBER_GET_NEXT 3 ...
- Mongo 分组后排序取时间最大的一整条数据对象
db.getCollection('product_protocol_new').aggregate([ {$sort:{"end_date":-1}}, {$group:{ _i ...