Quartz.NET开源作业调度框架系列(一):快速入门step by step
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中。Quartz.NET提供了巨大的灵活性但又兼具简单性。开发人员可用它快捷的创建并执行一个自动化作业。Quartz.NET有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等。
1 为什么选择Quartz.NET
在大部分的应用中,都需要对数据库进行定期备份 , 这个备份任务可以是每天晚上12:00或者每周星期二晚上12:00,或许仅仅每个月的最后一天执行。如果应用程序中需要这样的自动化执行任务 , 那么建议使用Quartz.NET调度器作为框架,为我们提供基础服务。 Quartz.NET允许开发人员根据时间间隔(或天)来调度作业 , 它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz.NET的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业.
2 如何创建一个简单的Quartz.NET
2.1 创建桌面应用程序并添加类库
用VS2012创建一个QuartzDemo的桌面应用程序 , 并用NuGet程序包管理添加Quartz.NET , 添加好类库后 , 项目文件如下图所示:

Quartz依赖库为Common.Logging和Common.Logging.Core , 二者需要一并导入 . 然后修改Form1的标题为QuartzDemo.
2.2 Form1定制
在Form1设计视图上 , 为该窗体添加一个TextBox和Panel , 并设置相关属性(背景色,字体等) , 如下图所示:

为了直观的执行定期任务 , 我们添加一个时序图(用Oxyplot控件) , 这里下载并引用Oxyplot.在Form1.cs文件中 ,首先引入需要的命名空间:
using Quartz;
using Quartz.Impl;
using Quartz.Job;
using System.Threading; using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
重载一个带参数的Form1构造方法:
private bool isFirst = true;
public Form1(string msg)
{
InitializeComponent();
_msg = msg;
try
{
//启动 scheduler
scheduler.Start();
// 定义一个job并和自定义的HelloJob进行绑定
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("HelloJob", "SimpleGroup")
.Build();
#region Cron Expressions
// ITrigger trigger2 = TriggerBuilder.Create()
//.WithIdentity("trigger3", "group1")
//.WithCronSchedule(" 0 0/5 * * * ?", x => x
// .WithMisfireHandlingInstructionFireAndProceed())
//.ForJob("job1", "group1")
//.Build();
#endregion //定义一个即时触发的触发器,(每隔1秒进行重复执行)
ITrigger trigger= TriggerBuilder.Create()
.WithIdentity("trigger1", "SimpleGroup")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds()
.RepeatForever())
.Build();
// 将job和trigger进行绑定,并告知 quartz 调度器用trigger去执行job
scheduler.ScheduleJob(job, trigger);
}
catch (SchedulerException se)
{
Console.WriteLine(se);
} }
在Form1的FormClosed事件,即窗体关闭后,将scheduler关闭:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//关闭 scheduler
scheduler.Shutdown();
}
在窗体加载时,创建一个时序图:
public OxyPlot.WindowsForms.PlotView Plot;
private LineSeries lineSeries = new LineSeries { Title = "即时监控(1秒)", StrokeThickness = };
private void Form1_Load(object sender, EventArgs e)
{
Plot = new OxyPlot.WindowsForms.PlotView();
Plot.Model = new PlotModel();
Plot.Dock = DockStyle.Fill;
this.panel1.Controls.Add(Plot); Plot.Model.PlotType = PlotType.XY;
Plot.Model.Background = OxyColor.FromRgb(, , );
Plot.Model.TextColor = OxyColor.FromRgb(, , ); // add Series and Axis to plot model
Plot.Model.Series.Add(lineSeries);
Plot.Model.Axes.Add(new LinearAxis());
}
定义一个SetMsg方法来更新消息:
private double xInit = ;
public bool SetMsg(string msg)
{
_msg = msg;
//号称NET4最简单的跨进程更新UI的方法
this.Invoke((MethodInvoker)delegate
{
// runs on UI thread
if (isFirst)
{
this.txtLog.AppendText("Hello to Quartz NET ! Created by JackWang 2015");
isFirst = false;
}
this.txtLog.AppendText(string.Format("\r\n$JackWang>> You get {0} message from Quartz MyJob...", _msg));
xInit = xInit + ;
lineSeries.Points.Add(new DataPoint(xInit,double.Parse(_msg)));
if (lineSeries.Points.Count > )
{
//保留最近50个点
lineSeries.Points.RemoveAt();
}
//更新图表数据
this.Plot.Model.InvalidatePlot(true); });
return true; }
2.3 定义一个HelloJob
在带参数的Form1构造方法中 , 创建的HelloJob的定义为:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace QuartzDemo
{
using Quartz;
using Quartz.Impl;
using Quartz.Job;
public class HelloJob : IJob
{
private static Form1 __instance = null;
public void Execute(IJobExecutionContext context)
{ if (isOpen("Form1"))
{
//获取当前Form1实例
__instance = (Form1)Application.OpenForms["Form1"];
//随机生成小于100的数
string num = new Random().Next().ToString();
//通过方法更新消息
__instance.SetMsg(num);
}
else
{
//__instance = new Form1("0");
//__instance.Show(); } }
/// <summary>
/// 判断窗体是否打开
/// </summary>
/// <param name="appName"></param>
/// <returns></returns>
private bool isOpen(string appName)
{
FormCollection collection = Application.OpenForms;
foreach (Form form in collection)
{
if (form.Name == appName)
{
return true;
}
}
return false;
}
}
}
注意修改Program.cs中用带参数的Form1构建方法进行实例创建:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(""));
}

3 最终效果
最终效果如下 , 每隔1秒,就是用随机的数来更新文本框和图表中的内容:

值得注意的是,如果用下面的代码格式,必须保证二者的名称完全一致,否则无法实现任务和触发器的绑定.

Quartz.NET开源作业调度框架系列(一):快速入门step by step的更多相关文章
- Quartz.NET开源作业调度框架系列(一):快速入门step by step-转
Quartz.NET是一个被广泛使用的开源作业调度框架 , 由于是用C#语言创建,可方便的用于winform和asp.net应用程序中.Quartz.NET提供了巨大的灵活性但又兼具简单性.开发人员可 ...
- 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开源作业调度框架系列(五):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的 ...
- Quartz.NET开源作业调度框架系列(二):CronTrigger
CronTriggers比SimpleTrigger更加的灵活和有用,对于比较复杂的任务触发规则,例如"每个星期天的晚上12:00"进行备份任务,SimpleTrigger就不能胜 ...
- Quartz.NET开源作业调度框架系列(二):CronTrigger-转
CronTriggers比SimpleTrigger更加的灵活和有用,对于比较复杂的任务触发规则,例如"每个星期天的晚上12:00"进行备份任务,SimpleTrigger就不能胜 ...
随机推荐
- 使用supervisor提高nodejs调试效率
如果你有PHP 开发经验,会习惯在修改PHP 脚本后直接刷新浏览器以观察结果,而你 在开发Node.js 实现的HTTP 应用时会发现,无论你修改了代码的哪一部份,都必须终止 Node.js 再重新运 ...
- JSP网站开发基础总结《十一》
继上一篇关于过滤器连总结后,本篇为大家详细介绍一下过滤器中过滤规则的dispatcher属性的使用,在servlet2.5中dispatcher的属性有四种,其中上一篇已经为大家介绍了error属性的 ...
- java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)
import java.util.concurrent.locks.*; class DuckMsg{ int size;//烤鸭的大小 String id;//烤鸭的厂家和标号 DuckMsg(){ ...
- 小实例窥探dotnet垃圾回收
今天项目调试时发现VS中有下面这样的现象. 说明,file.ServerLocation是一个完整的物理路径.第三句代码是错误的,保留只是因为它使用了"s"字符串. 个人认为当 ...
- Cocos2d-x 3.2 学习笔记(十四)保卫萝卜之界面UI
保卫萝卜~上一篇说了使用CocoStudio制作主界面,这里来完善主界面动画及后续界面(主题界面ThemeUI.场景选择界面SelectMapUI),主要涉及的控件PageView. 学习要 ...
- tomcat 容器生命周期lifecycle
1.复习java的事件机制 java事件机制包括三个部分:事件.事件监听器.事件源. 事件:一般继承自java.util.EventObject类,封装了事件源对象及跟事件相关的信息. 事件监听器:实 ...
- 利用ListView的基本方法实现效果
日常的开发工作经常需要ListView作为布局的组件,而且很多时候都会遇到需要自定义ListView的情况. 也有些问题并不需要自定义的ListView,基于原生的ListView就能实现,但需要灵活 ...
- Struts2 源码分析——Hello world
新建第一个应用程序 上一章我们讲到了关于struts2核心机制.对于程序员来讲比较概念的一章.而本章笔者将会亲手写一个Hello world的例子.所以如果对struts2使用比较了解的朋友,请跳过本 ...
- Chrome开发者工具详解(2)-Network面板
Chrome开发者工具详解(2)-Network面板 注: 这一篇主要讲解面板Network,参考了Google的相关文档,主要用于公司内部技术分享. Chrome开发者工具面板 面板上包含了Elem ...
- 原生js实现简洁的返回顶部组件
本文内容相当简单,所以没有发布到博客园首页,如果你不幸看到,那只能是我这篇文章的荣幸,谢谢你的大驾光临~(本博客返回顶部的功能就使用的是这个组件) 返回顶部组件是一种极其常见的网页功能,需求简单:页面 ...