想必大家在工作中经常会遇到这样类似的需求,在某个时间或者需要不间断的执行某个业务动作去满足任务需求。例如,我们写了一个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初探的更多相关文章

  1. Quartz.Net 学习之路02 初探Quartz.Net

    第二讲:简单的实例,看看Quartz.Net强在哪里? 直接上代码,代码里有注释: using System; using Quartz; using Quartz.Impl; namespace L ...

  2. Quartz每次调度时被执行两次

    [关键字:重复执行.重复调用.每次执行两次.执行2次] 前言: 先说一下,项目背景.由于组内某成员在用Maven搭建项目时不规范,导致项目的名称与实际访问项目名称不一致.在部署项目时,必需要配一下虚拟 ...

  3. 免费开源的DotNet任务调度组件Quartz.NET(.NET组件介绍之五)

    很多的软件项目中都会使用到定时任务.定时轮询数据库同步,定时邮件通知等功能..NET Framework具有“内置”定时器功能,通过System.Timers.Timer类.在使用Timer类需要面对 ...

  4. Quartz

    Quartz是一个开源的作业调度框架,它完全由Java写成,并设计用于J2SE和J2EE应用中.它提供了巨大的灵 活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度. eg: ja ...

  5. Spring Quartz实现任务调度

    任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维 ...

  6. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  7. topshelf和quartz内部分享

    阅读目录: 介绍 基础用法 调试及安装 可选配置 多实例支持及相关资料 quartz.net 上月在公司内部的一次分享,现把PPT及部分交流内容整理成博客. 介绍 topshelf是创建windows ...

  8. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...

  9. Quartz.net持久化与集群部署开发详解

    序言 我前边有几篇文章有介绍过quartz的基本使用语法与类库.但是他的执行计划都是被写在本地的xml文件中.无法做集群部署,我让它看起来脆弱不堪,那是我的罪过. 但是quart.net是经过许多大项 ...

随机推荐

  1. 监听iOS检测屏幕旋转状态,不需开启屏幕旋转

    -(void)rotation_icon:(float)n { UIButton *history_btn= [self.view viewWithTag:<#(NSInteger)#>] ...

  2. EMC机理------串扰

    转:电子工程师不得不知道的EMC机理------串扰(韬略科技EMC) 串扰是信号完整性中最基本的现象之一,在板上走线密度很高时串扰的影响尤其严重.我们知道,线性无缘系统满足叠加定理,如果受害线上有信 ...

  3. php的一个小坑,输出不了json_encode

    明明是旧代码,怎么换个地方就不执行了.一开始怀疑是Php的版本. 最后才知道是我的编辑器nodepad++给坑了.或许不是nodepad++的坑.总之,需要转化为utf-8格式编码即可

  4. Error executing DDL via JDBC Statement

    © 版权声明:本文为博主原创文章,转载请注明出处 1.问题描述: 启动hibernate测试案例时报错如下: org.hibernate.tool.schema.spi.CommandAcceptan ...

  5. matlab2017b linux版分享

    链接:https://pan.baidu.com/s/1smrTkFN 密码:cvb3 下载后请点关注并点赞,谢谢支持.

  6. Android 逐帧动画( Drawable 动画),这一篇就够了

    前言 作为 Android 最常见的两种动画形式,逐帧动画( Drawable 动画),有着极其广泛的应用,它的原理与早起的电影以及 GIF 类似,就是把一张的图,按顺序快速切换,这样一来看上去就好像 ...

  7. rst2pdf 中文

    上篇说到用pandoc转换为reST为pdf是使用LaTeX作为中间格式的,而今天要说的rst2pdf貌似是直接转换为pdf的. 安装和调用 rst2pdf目前只支持Python2.7,因此在创建vi ...

  8. mybatis前台传来一个String,后后台执行sql变成了true

    实际上参数传来的是一个字符串 3 ,不知道为什么会变成true 最后当然是查不到信息了.. 我在mapper映射文件里面使用了动态的where查询,我觉得跟这个关系不太大, 现在不知道怎么办,希望有思 ...

  9. maven项目The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    用Eclipse创建了一个maven web程序,使用tomcat8.5作为服务器,可以正常启动,但是却报如下错误 The superclass "javax.servlet.http.Ht ...

  10. android 在githup中的资源整理(转)

    1.Github开源Android组件资源整理(一) 个性化控件(View) 2.Github开源Android组件资源整理(二)ActionBar和Menu 3. Github开源Android组件 ...