前言
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().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(), );
DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddHours(), );
//创建并配置一个触发器
ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().StartAt(startTime).EndAt(endTime)
.WithSimpleSchedule(x=>x.WithIntervalInSeconds().WithRepeatCount())
.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(), );
DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddYears(), );
//创建并配置一个触发器
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天后关闭作业调度,将不在执行
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, );
if (m.EndRunTime == null)
{
m.EndRunTime = DateTime.MaxValue.AddDays(-);
}
DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, );
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 == )
{
#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 = ;
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 = ;
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() });
}
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 = ;
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 = , Msg = "停止任务计划成功!" }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
DoApplication.WriteLogFile(ex.Message + "/r/n" + ex.StackTrace);
return Json(new StatusView() { Status = -, 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 = , Msg = "启动成功!" }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{ DoApplication.WriteLogFile(ex.Message + "/r/n" + ex.StackTrace);
return Json(new StatusView() { Status = -, Msg = "启动失败!" }, JsonRequestBehavior.AllowGet);
}
}
最后注意:
1、这个项目完全使用啦cron-like表达式实现触发器配置,如果你对cron不了解,那么我上篇中有针对cron做介绍讲解,如果你对cron了解而没有一个合适的生成工具,那么入左上方2个群,找我。
2、这个项目部署在IIS中,那么就要设置应用程序池的回收机制为,永不回收,配置下,如果不会配置,入左上方2个群,找我。
Quartz.net开源作业调度框架使用详解的更多相关文章
-
Quartz.net开源作业调度框架使用详解(转)
前言 quartz.net作业调度框架是伟大组织OpenSymphony开发的quartz scheduler项目的.net延伸移植版本.支持 cron-like表达式,集群,数据库.功能性能强大更不 ...
-
Quartz.NET开源作业调度框架系列
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...
-
Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递
前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Conte ...
-
Quartz.NET开源作业调度框架系列(三):IJobExecutionContext 参数传递-转
前面写了关于Quartz.NET开源作业调度框架的入门和Cron Trigger , 这次继续这个系列, 这次想讨论一下Quartz.NET中的Job如何通过执行上下文(Execution Conte ...
-
Quartz.NET开源作业调度框架系列(一):快速入门step by step
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...
-
Quartz.NET开源作业调度框架系列(一):快速入门step by step-转
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...
-
Quartz.NET开源作业调度框架系列(五):AdoJobStore保存job到数据库
Quartz.NET 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger(用于定义调度时间的元素,即按照什么时间规则去执行任务) 和 job 是任务调度的元数 ...
-
Quartz.NET开源作业调度框架系列(四):Plugin Job
如果在Quartz.NET作业运行时我们想动态修改Job和Trigger的绑定关系,同时修改一些参数那么该怎么办呢?Quartz.NET提供了插件技术,可以通过在XML文件中对Job和Trigger的 ...
-
Quartz.NET开源作业调度框架系列(四):Plugin Job-转
如果在Quartz.NET作业运行时我们想动态修改Job和Trigger的绑定关系,同时修改一些参数那么该怎么办呢?Quartz.NET提供了插件技术,可以通过在XML文件中对Job和Trigger的 ...
随机推荐
-
thinkphp条件查询和模糊查询的一些方法
#文章管理 public function adminArticle(){ $adminArticle=M("article"); $arr_seach=$this->sea ...
-
在CentOS 6.6下安装与配置mysql
1.使用yum安装mysql yum list | grep mysql //查看mysql信息 yum install mysql-server.x86_64 //安装mysql sudo ap ...
-
kettle与各数据库建立链接的链接字符串
kettle与各数据库建立链接的链接字符串 Sybase: TO_DB_URL = jdbc:sybase:Tds:192.168.168.163:5000/testdb?charset=eucgb& ...
-
ORACLE SEQUENCE 介绍
在oracle中sequence就是所谓的序列号,每次取的时候它会自己主动添加,一般用在须要按序列号排序的地方. 1.Create Sequence 你首先要有CREATE SEQUENCE或者C ...
-
【APEX初步】【2】【sObjects与数据库】
由于apex是与数据库集成的.我们可以直接用apex访问数据库.每条记录就是一个SObject对象
-
UI培训怎么学才高效
随着互联网科技的爆炸式发展,UI设计越来越受到我们的青睐,绝大部分企业已成立U设计部门来提高自身影响力,但现在许多从事UI设计的人,都是从零基础过度过来的,他们不乏大牛,在阿里巴巴,在腾讯等国内一流企 ...
-
js代码大全(各种方法、属性)《转载》
事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture(); event.sr ...
-
.net core HttpContext(Http上下文)
在.NET Core中,只有Controller才能直接使用 HttpContext ,其他地方需要通过HttpContextAccessor来访问
-
WPF简单数据绑定
XAML: <!--#region 数据绑定控件--> <DataGrid x:Name="dataGrid" Grid.Column="2" ...
-
JavaScript1.6数组新特性和JQuery的几个工具方法
JavaScript 1.6 引入了几个新的Array 方法,具体的介绍见:New in JavaScript 1.6 .这些方法已经被写进了ECMA262 V5.现代浏览器(IE9/Firefox/ ...