前言

quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本。支持 cron-like表达式,集群,数据库。功能性能强大更不用说。

下载项目文档官网:http://www.quartz-scheduler.net/

项目中需引用:Common.Logging.dll , Common.Logging.Core.dll , Quartz.dll

下面给大家分解下我最近做的关于计划调度的一个小项目,来辅助理解quartz.net的功能和常用方法。

quartz.net的简单用法 -入门

如果你是quartz.net的使用新手,控制台入门这里,建议跟着做下,那么10分钟搞懂quartz.net也是 so easy 的事.

1.创建一个每隔3秒钟执行一次的计划调度

public class RunMain
{
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString("r"));
//1.首先创建一个作业调度池
ISchedulerFactory schedf = new StdSchedulerFactory();
IScheduler sched = schedf.GetScheduler();
//2.创建出来一个具体的作业
IJobDetail job = JobBuilder.Create<JobDemo>().Build();
//3.创建并配置一个触发器
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithSimpleSchedule(x=>x.WithIntervalInSeconds(3).WithRepeatCount(int.MaxValue)).Build();
//4.加入作业调度池中
sched.ScheduleJob(job, trigger);
//5.开始运行
sched.Start();
Console.ReadKey();
}
}
public class JobDemo : IJob
{
/// <summary>
/// 这里是作业调度每次定时执行方法
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
Console.WriteLine(DateTime.Now.ToString("r"));
}
}

Note:1、记下作业调度创建的顺序。2、上述代码执行结果是,每三秒执行一次JobDemo中的Execute,如果程序不停止,无休无止执行到天荒地老,呵呵,扯下蛋啊。

2.改进(丰富调度计划):上一个作业,我想让他每三秒执行一次,一共执行100次,开始执行时间设定在当前时间,结束时间我设定在2小时后,不过100次执行完没2小时候都不再执行。

    public class RunMain
{
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString("r"));
//首先创建一个作业调度池
ISchedulerFactory schedf = new StdSchedulerFactory();
IScheduler sched = schedf.GetScheduler();
//创建出来一个具体的作业
IJobDetail job = JobBuilder.Create<JobDemo>().Build();
//NextGivenSecondDate:如果第一个参数为null则表名当前时间往后推迟2秒的时间点。
DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddSeconds(1), 2);
DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddHours(2), 3);
//创建并配置一个触发器
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().StartAt(startTime).EndAt(endTime)
.WithSimpleSchedule(x=>x.WithIntervalInSeconds(3).WithRepeatCount(100))
.Build();
//加入作业调度池中
sched.ScheduleJob(job, trigger);
//开始运行
sched.Start();
Console.ReadKey();
}
}
public class JobDemo : IJob
{
/// <summary>
/// 这里是作业调度每次定时执行方法
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
Console.WriteLine(DateTime.Now.ToString("r"));
}
}

3.继续改进(cron-like使用):前两个作业调度都太简单,如果我想在每小时的第10,20,25,26,33,54分钟,每分钟的第1,10,14秒执行一次。那么上面显然是不能满足的。这是我就把cron-like表达式引入进来,以实现各种时间纬度的调用。

 public class RunMain
{
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString("r"));
//首先创建一个作业调度池
ISchedulerFactory schedf = new StdSchedulerFactory();
IScheduler sched = schedf.GetScheduler();
//创建出来一个具体的作业
IJobDetail job = JobBuilder.Create<JobDemo>().Build();
//NextGivenSecondDate:如果第一个参数为null则表名当前时间往后推迟2秒的时间点。
DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddSeconds(1), 2);
DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddYears(2), 3);
//创建并配置一个触发器
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create().StartAt(startTime).EndAt(endTime)
.WithCronSchedule("1,10,14 10,20,25,26,33,54 * * * ? ")
.Build();
//加入作业调度池中
sched.ScheduleJob(job, trigger);
//开始运行
sched.Start();
//挂起2天
Thread.Sleep(TimeSpan.FromDays(2));
//2天后关闭作业调度,将不在执行
sched.Shutdown();
Console.ReadKey();
}
}
public class JobDemo : IJob
{
/// <summary>
/// 这里是作业调度每次定时执行方法
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
Console.WriteLine(DateTime.Now.ToString("r"));
}
}

基于Quartz.net的作业调度项目详解

最终效果如开篇的第一个图所示。

下面主要说说,作业调度的中怎么定位到具体的作业调度,并给作业调度分组,命名,添加,启动,停止。

首先展示下表结构,项目中我叫作业调度为任务调度。

1、新增作业调度。

 /// <summary>
/// 任务计划
/// </summary>
public static IScheduler scheduler = null;
public static IScheduler GetScheduler()
{
if (scheduler != null)
{
return scheduler;
}
else
{
ISchedulerFactory schedf = new StdSchedulerFactory();
IScheduler sched = schedf.GetScheduler();
return sched;
}
}
/// <summary>
/// 添加任务计划
/// </summary>
/// <returns></returns>
public bool AddScheduleJob(WJ_ScheduleEntity m)
{
try
{
if (m != null)
{
if (m.StarRunTime == null)
{
m.StarRunTime = DateTime.Now;
}
DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 1);
if (m.EndRunTime == null)
{
m.EndRunTime = DateTime.MaxValue.AddDays(-1);
}
DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, 1);
scheduler = GetScheduler();
IJobDetail job = JobBuilder.Create<HttpJob>()
.WithIdentity(m.JobName, m.JobGroup)
.Build();
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.StartAt(starRunTime)
.EndAt(endRunTime)
.WithIdentity(m.JobName, m.JobGroup)
.WithCronSchedule(m.CronStr)
.Build();
scheduler.ScheduleJob(job, trigger);
scheduler.Start();
StopScheduleJob(m.JobGroup, m.JobName);
return true;
}
return false;
}
catch (Exception ex)
{
//DoApplication.WriteLogFile(ex.Message + "\r\n" + ex.StackTrace);
return false;
}
}

Note:1.这里作业调度执行的函数如下。2.上面的WithIdentity(m.JobName, m.JobGroup) ,是给作业调度加入组,和名称,方便我们针对哪一个作业计划,进行启动停止等操作。

 public class HttpJob : IJob
{
public void Execute(IJobExecutionContext context)
{
ThreadPool.QueueUserWorkItem(delegate(Object o)
{
try
{
//DoApplication.WriteLogFile(context.JobDetail.Key.Group + "---" + context.JobDetail.Key.Name + "---" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "---" + context.NextFireTimeUtc.Value.DateTime.AddHours(8).ToString("yyyy-MM-dd HH:mm:ss"));
var sm = new WJ_ScheduleManage().GetScheduleModel(new WJ_ScheduleEntity() { JobGroup = context.JobDetail.Key.Group, JobName = context.JobDetail.Key.Name });
new WJ_ScheduleManage().UpdateScheduleRunStatus(new WJ_ScheduleEntity() { JobGroup = context.JobDetail.Key.Group, JobName = context.JobDetail.Key.Name,RunStatus=(int)ADJ.Job.Entity.EnumType.JobRunStatus.执行中 });
ESBRequest req = new ESBRequest(sm.ServiceCode, sm.ApiCode);
DataResult result = req.Request();
new WJ_ScheduleManage().UpdateScheduleRunStatus(new WJ_ScheduleEntity() { JobGroup = context.JobDetail.Key.Group, JobName = context.JobDetail.Key.Name, RunStatus = (int)ADJ.Job.Entity.EnumType.JobRunStatus.待运行 });
if (result.Code == 1)
{
#region 加入执行明细
WJ_ScheduleDetailsEntity dm = new WJ_ScheduleDetailsEntity();
dm.ActionDescribe = "执行完成:" + result.Message ;
dm.ActionStep = (int)ADJ.Job.Entity.EnumType.JobStep.执行完成;
dm.CreateTime = DateTime.Now;
dm.JobGroup = context.JobDetail.Key.Group;
dm.JobName = context.JobDetail.Key.Name;
dm.IsSuccess = 1;
new WJ_ScheduleManage().AddScheduleDetails(dm);
#endregion
}
else
{
#region 加入执行明细
WJ_ScheduleDetailsEntity dm = new WJ_ScheduleDetailsEntity();
dm.ActionDescribe = "执行任务计划中,执行计划过程出错."+result.Message;
dm.ActionStep = (int)ADJ.Job.Entity.EnumType.JobStep.执行任务计划中;
dm.CreateTime = DateTime.Now;
dm.JobGroup = context.JobDetail.Key.Group;
dm.JobName = context.JobDetail.Key.Name;
dm.IsSuccess = 0;
new WJ_ScheduleManage().AddScheduleDetails(dm);
#endregion
}
new WJ_ScheduleManage().UpdateScheduleNextTime(new WJ_ScheduleEntity() { JobGroup = context.JobDetail.Key.Group, JobName = context.JobDetail.Key.Name, NextTime = context.NextFireTimeUtc.Value.DateTime.AddHours(8) });
}
catch (Exception ex)
{
#region 加入执行明细
WJ_ScheduleDetailsEntity dm = new WJ_ScheduleDetailsEntity();
dm.ActionDescribe = "执行任务计划中,执行计划过程出错:" + ex.Message + "/r/n" + ex.StackTrace;
dm.ActionStep = (int)ADJ.Job.Entity.EnumType.JobStep.执行任务计划中;
dm.CreateTime = DateTime.Now;
dm.JobGroup = context.JobDetail.Key.Group;
dm.JobName = context.JobDetail.Key.Name;
dm.IsSuccess = 0;
new WJ_ScheduleManage().AddScheduleDetails(dm);
#endregion
DoApplication.WriteLogFile(ex.Message + "\r\n" + ex.StackTrace);
}
});
}
}

note:这里执行的Execute方法参数IJobExecutionContext 中,会自动把作业调度的详细信息带过来,作业名称,作业组名,作业下次执行时间,作业执行时间等等,这里的内容也是至关重要的,比如根据作业组,作业名称我们可以从数据库找到相应的作业调度详细,更新操作数据库。

2、针对某个作业计划进行停止,启动。

 /// <summary>
/// 暂停指定任务计划
/// </summary>
/// <returns></returns>
public JsonResult StopScheduleJob(string jobGroup, string jobName)
{
try
{
scheduler = GetScheduler();
scheduler.PauseJob(new JobKey(jobName, jobGroup));
new WJ_ScheduleManage().UpdateScheduleStatus(new WJ_ScheduleEntity() { JobName = jobName, JobGroup = jobGroup, Status = (int)ADJ.Job.Entity.EnumType.JobStatus.已停止 });
return Json(new StatusView() { Status = 0, Msg = "停止任务计划成功!" }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
DoApplication.WriteLogFile(ex.Message + "/r/n" + ex.StackTrace);
return Json(new StatusView() { Status = -1, Msg = "停止任务将计划失败!" }, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// 开启指定的任务计划
/// </summary>
/// <returns></returns>
public JsonResult RunScheduleJob(string jobGroup, string jobName)
{
try
{
var sm = new WJ_ScheduleManage().GetScheduleModel(new WJ_ScheduleEntity() { JobName = jobName, JobGroup = jobGroup });
AddScheduleJob(sm);
sm.Status = (int)ADJ.Job.Entity.EnumType.JobStatus.已启用;
new WJ_ScheduleManage().UpdateScheduleStatus(sm);
scheduler = GetScheduler();
scheduler.ResumeJob(new JobKey(jobName, jobGroup));
return Json(new StatusView() { Status = 0, Msg = "启动成功!" }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{ DoApplication.WriteLogFile(ex.Message + "/r/n" + ex.StackTrace);
return Json(new StatusView() { Status = -1, Msg = "启动失败!" }, JsonRequestBehavior.AllowGet);
}
}

最后注意:

1、这个项目完全使用啦cron-like表达式实现触发器配置,如果你对cron不了解,那么我上篇中有针对cron做介绍讲解,如果你对cron了解而没有一个合适的生成工具,那么入左上方2个群,找我。

2、这个项目部署在IIS中,那么就要设置应用程序池的回收机制为,永不回收,配置下,如果不会配置,入左上方2个群,找我。

Quartz.net开源作业调度框架使用详解(转)的更多相关文章

  1. Quartz.net开源作业调度框架使用详解

    前言 quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本.支持 cron-like表达式,集群,数据库.功能性能强大更不 ...

  2. Quartz.NET开源作业调度框架系列

    Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...

  3. Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递

    前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Conte ...

  4. Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递-转

    前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Conte ...

  5. Quartz.NET开源作业调度框架系列(一):快速入门step by step

    Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...

  6. Quartz.NET开源作业调度框架系列(一):快速入门step by step-转

    Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...

  7. Quartz.NET开源作业调度框架系列(五):AdoJobStore保存job到数据库

    Quartz.NET 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger(用于定义调度时间的元素,即按照什么时间规则去执行任务) 和 job 是任务调度的元数 ...

  8. Quartz.NET开源作业调度框架系列(四):Plugin Job

    如果在Quartz.NET作业运行时我们想动态修改Job和Trigger的绑定关系,同时修改一些参数那么该怎么办呢?Quartz.NET提供了插件技术,可以通过在XML文件中对Job和Trigger的 ...

  9. Quartz.NET开源作业调度框架系列(四):Plugin Job-转

    如果在Quartz.NET作业运行时我们想动态修改Job和Trigger的绑定关系,同时修改一些参数那么该怎么办呢?Quartz.NET提供了插件技术,可以通过在XML文件中对Job和Trigger的 ...

随机推荐

  1. Activiti系列: 如何给内置表单添加字段类型

     对于内置的表单,除了原来支持的几种数据类型(string, long, enum, date, boolean, collection)之外,还可以自定义数据类型,比如增加一个javascript数 ...

  2. [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝

    13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...

  3. jenkins publish over ssh使用

    1.在需要远程的ubuntu服务器上生成密钥,指令:ssh-keygen   一路默认下去,会在~/.ssh目录下生成 id_rsa(私钥).id_rsa.pub(公钥) 2.复制公钥文件id_rsa ...

  4. php 读取文件的几种方法

    文件操作的三个步骤,打开,操作,关闭.$fopen=fopen(路径,方式),fwrite($fopen,写入的字符串);fclose($fopen). 其中打开方式有如下几种方式: 模式 描述 r ...

  5. IT技术的进化道路

    IT技术是人类发明的,同时也是给人类服务的,这项技术的进化,就是距离人越来越近,大体上是: 大型机时代: 离人类的距离超过100米. 小型机时代: 离人类的距离前进到10米. PC机时代: 离人类的距 ...

  6. jqurey 遍历 div内的所有input单选复选按钮并判断是否选中及Attr(checked)无效的解决

    关于页面前面标签 <ul> @{ foreach (var item in vote) { if (!string.IsNullOrEmpty(item.Img)) { <li cl ...

  7. [USACO2003][poj2138]Travel Games(dp/最长路)

    http://poj.org/problem?id=2138 题意:给你一些单词和初始单词,在初始单词的任意位置你可以加任意一个字母,使得这个新单词在给的单词中有所出现,然后在这样不断迭代下去,让你求 ...

  8. 每天一个linux命令(53):wget命令

    Linux系统中的wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTTPS和FTP协 ...

  9. HDU 5115 Dire Wolf 区间dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5115 Dire Wolf Time Limit: 5000/5000 MS (Java/Others ...

  10. log4j:WARN Please initialize the log4j system properly.解决

    log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlA ...