Oracle详尽讲解Quartz.NET

     前言:8月份翻了Quartz.NET的合法课程:开源之课业调度框架 –
Quartz.NET,
有的爱人抱怨难用,确实,目前Qiartz.NET的最新版本要0.6,还留存多bug和非完善之地方。本文使用同一雨后春笋代码示例介绍
Quartz.NET API,演示其的体制,例如作业、触发器、作业仓库。

     Quartz.NET是一个开源的学业调度框架,是OpenSymphony 的 Quartz
API的.NET移植,它用C#形容成,可用于winform和asp.net应用被。它提供了英雄的灵活性而非牺牲简单性。你可知用它们来吧实施一个作业要创立简单的要么复杂的调度。它产生许多表征,如:数据库支持,集群,插件,支持cron-like表达式等等。

你已经待以执行一个职责为?这个任务每天要每周星期二晚上11:30,或许就每个月份的结尾一天行。一个机关执行要毫无干预的天职在实践进程遭到如出一个严重错误,应用会知道到该行破产并尝试还履行呢?你跟汝的团是用.NET编程吗?如果这些题材备受其他一个你答应是,那么您当下Quartz.NET调度器。
Quartz.NET允许开发人员根据日间隔(或上)来调度作业。它实现了课业和触发器的基本上针对性多关系,还会把多单作业和差之触发器关联。整合了
Quartz.NET的应用程序可以用来自不同事件的学业,还可为一个轩然大波做多独作业.

Quartz.NET入门

使起利用 Quartz.NET,需要为此 Quartz.NET API 对品种进展安排。步骤如下:

  1. 到http://quartznet.sourceforge.net/download.html下载 Quartz.NET
    API,最新版本是0.6

  2. 解压缩Quartz.NET-0.6.zip 到目录,根据你的种情况于是Visual Studio
    2003还是Visual Studio
    2005打开相应工程,编译。你得以她推广上自己之使用被。Quartz.NET框架只是待少数之老三方库,并且这些三在库是必不可少的,你异常可能已以利用这些库了。

3.
每当Quartz.NET有一个称为quartz.properties的配置文件,它同意而改改框架运行时环境。缺省是使Quartz.dll里面的quartz.properties文件。当然你可在应用程序配置文件中召开相应的布置,下面是一个安排文件示例:

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<configSections>

<section name=”quartz”
type=”System.Configuration.NameValueSectionHandler, System,
Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089″
/>

</configSections>

<quartz>

<add key=”quartz.scheduler.instanceName”
value=”ExampleDefaultQuartzScheduler” />

<add key=”quartz.threadPool.type”
value=”Quartz.Simpl.SimpleThreadPool, Quartz” />

<add key=”quartz.threadPool.threadCount” value=”10″ />

<add key=”quartz.threadPool.threadPriority” value=”2″ />

<add key=”quartz.jobStore.misfireThreshold” value=”60000″ />

<add key=”quartz.jobStore.type” value=”Quartz.Simpl.RAMJobStore,
Quartz” />

</quartz>

</configuration>

以便利读者,我们利用Quartz.NET的例证代码来诠释,现在来拘禁一下 Quartz
API 的关键组件。

调度器和学业

Quartz.NET框架的中坚是调度器。调度器负责管理Quartz.NET应用运行时环境。调度器不是恃自己开有的劳作,而是靠框架内局部万分重大的构件。Quartz不仅仅是线程和线程管理。为力保可伸缩性,Quartz.NET采用了根据多线程的架。
启动时,框架初始化一效worker线程,这套线程被调度器用来实施预定的功课。这即是Quartz.NET怎样能连作运行多单作业的原理。Quartz.NET依赖一仿松耦合的线程池管理部件来管理线程环境。作业是一个执任务之简单.NET类。任务可以是另C#\VB.NET代码。只需要而兑现Quartz.IJob接口并且以产出严重错误情况下丢来JobExecutionException异常即可。

IJob接口包含唯一的一个方法Execute(),作业由这里开实行。一旦落实了IJob接口和Execute
()方法,当Quartz.NET确定拖欠是学业运行的早晚,它用调用你的功课。Execute()方法外虽完全是你如果举行的作业。

经过实现 Quartz.IJob接口,可以要 .NET 类变成可尽之。清单 1 提供了
Quartz.IJob作业的一个演示。这个类用一长条非常简单的输出语句覆盖了
Execute(JobExecutionContext context)
方法。这个法子好涵盖我们纪念要履的其他代码(所有的代码示例都根据
Quartz.NET 0.6 ,它是编写这篇文章时的康乐发行版)。

清单 1:作业

using System;

using System.Collections.Generic;

using System.Text;

using Common.Logging;

using Quartz;

namespace QuartzBeginnerExample

{

public class SimpleQuartzJob : IJob

{

private static ILog _log =
LogManager.GetLogger(typeof(SimpleQuartzJob));

/// <summary>

/// Called by the <see cref=”IScheduler” /> when a

/// <see cref=”Trigger” /> fires that is associated with

/// the <see cref=”IJob” />.

/// </summary>

public virtual void Execute(JobExecutionContext context)

{

try

{

// This job simply prints out its job name and the

// date and time that it is running

string jobName = context.JobDetail.FullName;

_log.Info(“Executing job: ” + jobName + ” executing at ” +
DateTime.Now.ToString(“r”));

}

catch (Exception e)

{

_log.Info(“— Error in job!”);

JobExecutionException e2 = new JobExecutionException(e);

// this job will refire immediately

e2.RefireImmediately = true;

throw e2;

}

}

}

}

恳请留心,Execute 方法接受一个 JobExecutionContext
对象作为参数。这个目标提供了学业实例的运转时达成下文。特别地,它提供了针对性调度器和触发器的访问,这两头协作来启动作业及学业的
JobDetail 对象的实行。Quartz.NET 通过将作业的状态在 JobDetail
对象中并于 JobDetail
构造函数启动一个学业的实例,分离了作业的实践及作业周围的状态。JobDetail
对象储存作业的侦听器、群组、数据映射、描述和学业的其他性能。

作业及触发器:

Quartz.NET设计者做了一个规划选择来打调度分离开作业。Quartz.NET中的触发器用来报告调度程序作业什么时候接触。框架提供了扳平拿触发器类型,但少单顶常用之是SimpleTrigger和CronTrigger。SimpleTrigger为急需简单打火调度而计划。

典型地,如果您待以给定的光阴和重次数要少不行点火之间等的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果您闹为数不少繁杂的功课调度,那么可能需要CronTrigger。

CronTrigger是根据Calendar-like调度的。当您要以除星期六与星期他之每天上午10触及半实施作业时,那么相应采取CronTrigger。正而它的名所暗示的那么,CronTrigger是基于Unix克隆表达式的。

Cron表达式被用来配置CronTrigger实例。Cron表达式是一个是因为7个子表达式组成的字符串。每个子表达式都讲述了一个单身的日程细节。这些子表达式用空格分隔,分别表示:

  1. Seconds 秒

  2. Minutes 分钟

  3. Hours 小时

  4. Day-of-Month 月受到之天

  5. Month 月

  6. Day-of-Week 周中的上

  7. Year (optional field) 年(可选的地方)

一个cron表达式的事例字符串为”0 0 12 ? *
WED”,这表示“每周三的中午12:00”。

单个子表达式可以分包限制或列表。例如:前面例子中之周中的龙立个域(这里是”WED”)可以吃调换为”MON-FRI”,
“MON, WED, FRI”或者甚至”MON-WED,SAT”。

通配符(’*’)可以叫用来表示域中“每个”可能的价值。因此在”Month”域中之*意味着每个月,而以Day-Of-Week域中之*尽管象征“周中的各级一样上”。

有的地域中之价都发出特定的官方范围,这些价值的合法范围相当醒目,例如:秒和分域的合法值为0至59,小时之官方范围是0暨23,Day-of-Month中值得合法凡范围是0届31,但是急需专注不同之月度受的数不同。月份的法定值是0及11。或者用字符串JAN,FEB
MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV
及DEC来代表。Days-of-Week可以为此1交7来代表(1=星期日)或者用字符串SUN,
MON, TUE, WED, THU, FRI 和SAT来表示.

‘/’字符用来表示值的增量,例如,
如果分钟域中放入’0/15’,它象征“每隔15分钟,从0开始”,如果当卖中域中行使’3/20’,则表示“小时吃各隔20分钟,从第3分钟开始”或者另外相同的样式就是’3,23,43’。

‘?’字符可以用在day-of-month及day-of-week域中,它因此来表示“没有指定值”。这对欲指定一个要么简单单处的价值如果不欲针对另地方进行设置来说相当实用。

‘L’字符可以在day-of-month及day-of-week中应用,这个字符是”last”的简写,但是当有限个地段中的意义不同。例如,在day-of-month域中之”L”表示此月的末段一上,即,一月之31日,非闰年的二月底28日。如果她因此在day-of-week中,则表示”7″或者”SAT”。但是如果以day-of-week域中,这个字符跟于别的值后面,则意味着”当月底末段之周XXX”。例如:”6L”
或者
“FRIL”都表示本月底结尾一个周五。当使用’L’选项时,最紧要之是决不指定列表或者值范围,否则会促成乱。

‘W’
字符用来指定距离被定日最接近的周几(在day-of-week域中指定)。例如:如果您啊day-of-month域指定为”15W”,则代表“距离月被15声泪俱下以来的周几”。

‘#’表示表示月被之第几独周几。例如:day-of-week域中的”6#3″ 或者
“FRI#3″表示“月被第三单周五”。

用作一个例证,下面的Quartz.NET克隆表达式将于小礼拜一到星期五之每日上午10沾15区划执行一个学业。

0 15 10 ? * MON-FRI

下的表达式

0 15 10 ? * 6L 2007-2010

以在2007年至2010年之每个月份的结尾一个星期五上午10触及15私分执行作业。你不可能用SimpleTrigger来举行这些业务。你得就此两者间的别样一个,但哪个跟合适则取决于你的调度需要。

清单 2 中之 SimpleTrigger 展示了触发器的基本功:

清单2 SimpleTriggerRunner.cs

using System;

using System.Collections.Generic;

using System.Text;

using Common.Logging;

using Quartz;

using Quartz.Impl;

namespace QuartzBeginnerExample

{

public class SimpleTriggerRunner

{

public virtual void Run()

{

ILog log = LogManager.GetLogger(typeof(SimpleTriggerExample));

log.Info(“——- Initializing ——————-“);

// First we must get a reference to a scheduler

ISchedulerFactory sf = new StdSchedulerFactory();

IScheduler sched = sf.GetScheduler();

log.Info(“——- Initialization Complete ——–“);

log.Info(“——- Scheduling Jobs —————-“);

// jobs can be scheduled before sched.start() has been called

// get a “nice round” time a few seconds in the future…

DateTime ts = TriggerUtils.GetNextGivenSecondDate(null, 15);

// job1 will only fire once at date/time “ts”

JobDetail job = new JobDetail(“job1”, “group1”, typeof(SimpleJob));

SimpleTrigger trigger = new SimpleTrigger(“trigger1”, “group1”);

// set its start up time

trigger.StartTime = ts;

// set the interval, how often the job should run (10 seconds here)

trigger.RepeatInterval = 10000;

// set the number of execution of this job, set to 10 times.

// It will run 10 time and exhaust.

trigger.RepeatCount = 100;

// schedule it to run!

DateTime ft = sched.ScheduleJob(job, trigger);

log.Info(string.Format(“{0} will run at: {1} and repeat: {2} times,
every {3} seconds”,

job.FullName, ft.ToString(“r”), trigger.RepeatCount,
(trigger.RepeatInterval / 1000)));

log.Info(“——- Starting Scheduler —————-“);

// All of the jobs have been added to the scheduler, but none of the
jobs

// will run until the scheduler has been started

sched.Start();

log.Info(“——- Started Scheduler —————–“);

log.Info(“——- Waiting 30 seconds… ————–“);

try

{

// wait 30 seconds to show jobs

Thread.Sleep(30 * 1000);

// executing…

}

catch (ThreadInterruptedException)

{

}

log.Info(“——- Shutting Down ———————“);

sched.Shutdown(true);

log.Info(“——- Shutdown Complete —————–“);

// display some stats about the schedule that just ran

SchedulerMetaData metaData = sched.GetMetaData();

log.Info(string.Format(“Executed {0} jobs.”, metaData.NumJobsExecuted));

}

}

}

清单 2 开始经常实例化一个
SchedulerFactory,获得是调度器。就如前议论过之,创建 JobDetail
对象时,它的构造函数要经受一个 Job 作为参数。顾名思义,SimpleTrigger
实例相当原始。在创建对象之后,设置几独着力性能为当时调度任务,然后每 10
秒重复相同不好,直到作业给实施 100 次。

还起其他许多道得以操纵
SimpleTrigger。除了指定重复次数及重间隔,还得指定作业在特定日历时间执行,只待于得执行的极致丰富时或者优先级(稍后讨论)。执行的极丰富时可以覆盖指定的再度次数,从而确保作业的运转不会见超过最丰富日子。

清单 3 显示了 CronTrigger 的一个示范。请留心 SchedulerFactory、Scheduler
和 JobDetail 的实例化,与 SimpleTrigger
示例中的实例化是同样之。在此示例中,只是修改了触发器。这里指定的 cron
表达式(“0/5 * * * * ?”)安排任务每 5 秒执行同一次等。

清单3 CronTriggerRunner.cs

using System;

using System.Collections.Generic;

using System.Text;

using Common.Logging;

using Quartz;

using Quartz.Impl;

using System.Threading;

namespace QuartzBeginnerExample

{

public class CronTriggerRunner

{

public virtual void Run()

{

ILog log = LogManager.GetLogger(typeof(CronTriggerRunner));

log.Info(“——- Initializing ——————-“);

// First we must get a reference to a scheduler

ISchedulerFactory sf = new StdSchedulerFactory();

IScheduler sched = sf.GetScheduler();

log.Info(“——- Initialization Complete ——–“);

log.Info(“——- Scheduling Jobs —————-“);

// jobs can be scheduled before sched.start() has been called

// job 1 will run every 20 seconds

JobDetail job = new JobDetail(“job1”, “group1”,
typeof(SimpleQuartzJob));

CronTrigger trigger = new CronTrigger(“trigger1”, “group1”, “job1”,
“group1”);

trigger.CronExpressionString = “0/20 * * * * ?”;

sched.AddJob(job, true);

DateTime ft = sched.ScheduleJob(trigger);

log.Info(string.Format(“{0} has been scheduled to run at: {1} and repeat
based on expression: {2}”, job.FullName, ft.ToString(“r”),
trigger.CronExpressionString));

log.Info(“——- Starting Scheduler —————-“);

// All of the jobs have been added to the scheduler, but none of the

// jobs

// will run until the scheduler has been started

sched.Start();

log.Info(“——- Started Scheduler —————–“);

log.Info(“——- Waiting five minutes… ————“);

try

{

// wait five minutes to show jobs

Thread.Sleep(300 * 1000);

// executing…

}

catch (ThreadInterruptedException)

{

}

log.Info(“——- Shutting Down ———————“);

sched.Shutdown(true);

log.Info(“——- Shutdown Complete —————–“);

SchedulerMetaData metaData = sched.GetMetaData();

log.Info(string.Format(“Executed {0} jobs.”, metaData.NumJobsExecuted));

}

}

}

倘齐所示,只用作业以及触发器,就会访问大量的效能。但是,Quartz
是单长而活的调度包,对于甘愿钻研其的总人口吧,它还提供了双重多职能。下一样节讨论
Quartz 的部分尖端特性。

学业管理及储存

作业要为调度,调度器需要记住并且跟踪作业及它的实践次数。如果您的课业是30分钟后要每30秒调用,这不是可怜有因此。事实上,作业执行要格外标准和就调用在给调度作业上之Execute()方法。Quartz通过一个叫作作业存储(JobStore)的概念来做功课存储和管理。

得力作业存储

Quartz提供简单栽基本功课存储类型。第一种植类型叫做RAMJobStore,它应用一般的内存来持久化调度程序信息。这种作业存储类型最轻配置、构造与运行。Quartz.net缺省下的哪怕是RAMJobStore。对许多动来说,这种作业存储已经足够了。

可,因为调度程序信息是储存在吃分配在内存里面,所以,当应用程序停止运行时,所有调度信息以让遗失。如果您得以还启航之间持久化调度信息,则用待第二种植类型的功课存储。为了修正这个问题,Quartz.NET
提供了 AdoJobStore。顾名思义,作业仓库通过
ADO.NET把所有数据在数据库中。数据持久性的代价就是是性质降低与复杂性的增长。它以具备的数据经过ADO.NET保存至数据库可受到。它的布置要比RAMJobStore稍微复杂,同时速度为绝非那么快。但是性能的败笔不是生差,尤其是一旦你当数码库表的主键上树目录。

设置AdoJobStore

AdoJobStore几乎可以以另外数据库及行事,它广泛地动Oracle, MySQL, MS
SQLServer2000, HSQLDB, PostreSQL 以及
DB2。要下AdoJobStore,首先得创造同模拟Quartz使用的数量库表,可以于Quartz
的database\tables找到创建库表的SQL脚本。如果无找到你的数据库类型的本子,那么找到一个已有的,修改成为您数据库所待的。需要小心的等同项事情就是是兼备Quartz库表名都为QRTZ_当前缀(例如:表”QRTZ_TRIGGERS”,及”QRTZ_JOB_DETAIL”)。实际上,可以你得将前缀设置为另外你想要之前缀,只要你告诉AdoJobStore那个前缀是呀即可(在公的Quartz属性文件被布置)。对于一个数据库中以多独scheduler实例,那么配置不同之前缀可以创建多模仿库表,十分有效。

要是数据库表已经创办,在配备与启动AdoJobStore之前,就用作出一个更为重要之仲裁。你而控制以公的行使中需什么种的作业。如果非思用scheduling命令绑到其他的事务上,那么您得通过对JobStore使用JobStoreTX来吃Quartz帮您管理作业(这是最最广的挑选)。

末了之问号就是怎么样立获得数据库联网的数据源(DataSource)。Quartz属性中定义数据源是通过提供具有接数据库的音信,让Quartz自己创造及治本数据源。

假定动AdoJobStore(假定使用StdSchedulerFactory),首先需装Quartz配置中的quartz.jobStore.type属性为Quartz.Impl.AdoJobStore.JobStoreTX,
Quartz。

配置 Quartz使用 JobStoreTx

quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz

下同样步,需要也JobStore 选择一个DriverDelegate ,
DriverDelegate负责做指定数据库的持有ADO.NET工作。StdADO.NETDelegate是一个运vanilla”
ADO.NET代码(以及SQL语句)来形成工作的代理。如果数据库没有其它指定的代办,那么就是试用这个代理。只有当用StdADO.NETDelegate发生问题时常,我们才见面使用数据库特定的代理(这看起非常乐观。其他的代理可以于Quartz.Impl.AdoJobStor命名空间找到。)。其他的代理包括PostgreSQLDelegate
( 专也PostgreSQL 7.x)。

要是选择好了代办,就将它们的名字设置于AdoJobStore。

配置AdoJobStore 使用DriverDelegate

quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz

连接下去,需要为JobStore指定所利用的数据库表前缀(前面议论了)。

布AdoJobStore的数据库表前缀

quartz.jobStore.tablePrefix = QRTZ

接下来用设置JobStore所使用的数据源。必须在Quartz属性中定义已命名的数据源,比如,我们指定Quartz使用名吧”default”的数据源(在布局文件之外地方定义)。

配置 AdoJobStore使用数据持续的名

properties[“quartz.jobStore.dataSource”] = “default”

终极,需要配备数据源的用的Ado.net数据提供者和数据库连接串,数据库连接串是规范的Ado.net
数据库连接的连续串。数据库提供者是关系数据库同Quartz.net之间维持小耦合的数据库的连天提供者.

布置AdoJobStore使用数据持续的数据库连接串和数据库提供者

quartz.dataSource.default.connectionString =
Server=(local);Database=quartz;Trusted_Connection=True;

quartz.dataSource.default.provider= SqlServer-11

目前Quartz.net支持之以下数据库的数目提供者:

l SqlServer-11 – SQL Server driver for .NET Framework 1.1

l SqlServer-20 – SQL Server driver for .NET Framework 2.0

l OracleClient-20 – Microsoft’s Oracle Driver (comes bundled with .NET
Framework)

l OracleODP-20 – Oracle’s Oracle Driver

l MySql-10 – MySQL Connector/.NET v. 1.0.7

l MySql-109 – MySQL Connector/.NET v. 1.0.9

l MySql-50 – MySQL Connector/.NET v. 5.0 (.NET 2.0)

l MySql-51 – MySQL Connector/:NET v. 5.1 (.NET 2.0)

l SQLite1044 – SQLite ADO.NET 2.0 Provider v. 1.0.44 (.NET 2.0)

如若Scheduler非常繁忙(比如,执行的天职数多与线程池的数码同样,那么你待对地部署DataSource的连年数量为线程池数量。为了指示AdoJobStore所有的JobDataMaps中的价都是字符串,并且会盖“名字-值”对的法子囤而非是以复杂对象的序列化形式储存于BLOB字段遭遇,应装
quartz.jobStore.usePropertiess配置参数的价值吗”true”(这是缺失省的法)。这样做,从老来拘禁挺安全,这样避免了针对性存储在BLOB中的非字符串的序列化对象的类型转换问题。

清单 4 展示了
AdoJobStore提供的多寡持久性。就比如在面前的示范中相同,先打初始化
SchedulerFactory 和 Scheduler
开始。然后,不再需要初始化作业及触发器,而是要博触发器群组名称列表,之后对于每个群组名称,获取触发器名称列表。请留心,每个现有的学业都应当为此
Scheduler. RescheduleJob ()
方法重新调度。仅仅重新初始化在以前的应用程序运行时停的课业,不会见对地装载触发器的性质。

清单4 AdoJobStoreRunner.cs

public class AdoJobStoreRunner : IExample

{

public string Name

{

get { return GetType().Name; }

}

private static ILog _log =
LogManager.GetLogger(typeof(AdoJobStoreRunner));

public virtual void CleanUp(IScheduler inScheduler)

{

_log.Warn(“***** Deleting existing jobs/triggers *****”);

// unschedule jobs

string[] groups = inScheduler.TriggerGroupNames;

for (int i = 0; i < groups.Length; i++)

{

String[] names = inScheduler.GetTriggerNames(groups[i]);

for (int j = 0; j < names.Length; j++)

inScheduler.UnscheduleJob(names[j], groups[i]);

}

// delete jobs

groups = inScheduler.JobGroupNames;

for (int i = 0; i < groups.Length; i++)

{

String[] names = inScheduler.GetJobNames(groups[i]);

for (int j = 0; j < names.Length; j++)

inScheduler.DeleteJob(names[j], groups[i]);

}

}

public virtual void Run(bool inClearJobs, bool inScheduleJobs)

{

NameValueCollection properties = new NameValueCollection();

properties[“quartz.scheduler.instanceName”] = “TestScheduler”;

properties[“quartz.scheduler.instanceId”] = “instance_one”;

properties[“quartz.threadPool.type”] = “Quartz.Simpl.SimpleThreadPool,
Quartz”;

properties[“quartz.threadPool.threadCount”] = “5”;

properties[“quartz.threadPool.threadPriority”] = “Normal”;

properties[“quartz.jobStore.misfireThreshold”] = “60000”;

properties[“quartz.jobStore.type”] =
“Quartz.Impl.AdoJobStore.JobStoreTX, Quartz”;

properties[“quartz.jobStore.driverDelegateType”] =
“Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz”;

properties[“quartz.jobStore.useProperties”] = “false”;

properties[“quartz.jobStore.dataSource”] = “default”;

properties[“quartz.jobStore.tablePrefix”] = “QRTZ_”;

properties[“quartz.jobStore.clustered”] = “true”;

// if running MS SQL Server we need this

properties[“quartz.jobStore.selectWithLockSQL”] = “SELECT * FROM
{0}LOCKS UPDLOCK WHERE LOCK_NAME = @lockName”;

properties[“quartz.dataSource.default.connectionString”] =
@”Server=LIJUNNIN-PC\SQLEXPRESS;Database=quartz;Trusted_Connection=True;”;

properties[“quartz.dataSource.default.provider”] = “SqlServer-20”;

// First we must get a reference to a scheduler

ISchedulerFactory sf = new StdSchedulerFactory(properties);

IScheduler sched = sf.GetScheduler();

if (inClearJobs)

{

CleanUp(sched);

}

_log.Info(“——- Initialization Complete ———–“);

if (inScheduleJobs)

{

_log.Info(“——- Scheduling Jobs ——————“);

string schedId = sched.SchedulerInstanceId;

int count = 1;

JobDetail job = new JobDetail(“job_” + count, schedId,
typeof(SimpleQuartzJob));

// ask scheduler to re-Execute this job if it was in progress when

// the scheduler went down…

job.RequestsRecovery = true;

SimpleTrigger trigger = new SimpleTrigger(“trig_” + count, schedId, 20,
5000L);

trigger.StartTime = DateTime.Now.AddMilliseconds(1000L);

sched.ScheduleJob(job, trigger);

_log.Info(string.Format(“{0} will run at: {1} and repeat: {2} times,
every {3} seconds”, job.FullName, trigger.GetNextFireTime(),
trigger.RepeatCount, (trigger.RepeatInterval / 1000)));

count++;

job = new JobDetail(“job_” + count, schedId, typeof(SimpleQuartzJob));

// ask scheduler to re-Execute this job if it was in progress when

// the scheduler went down…

job.RequestsRecovery = (true);

trigger = new SimpleTrigger(“trig_” + count, schedId, 20, 5000L);

trigger.StartTime = (DateTime.Now.AddMilliseconds(2000L));

sched.ScheduleJob(job, trigger);

_log.Info(string.Format(“{0} will run at: {1} and repeat: {2} times,
every {3} seconds”, job.FullName, trigger.GetNextFireTime(),
trigger.RepeatCount, (trigger.RepeatInterval / 1000)));

count++;

job = new JobDetail(“job_” + count, schedId, typeof(SimpleQuartzJob));

// ask scheduler to re-Execute this job if it was in progress when

// the scheduler went down…

job.RequestsRecovery = (true);

trigger = new SimpleTrigger(“trig_” + count, schedId, 20, 3000L);

trigger.StartTime = (DateTime.Now.AddMilliseconds(1000L));

sched.ScheduleJob(job, trigger);

_log.Info(string.Format(“{0} will run at: {1} and repeat: {2} times,
every {3} seconds”, job.FullName, trigger.GetNextFireTime(),
trigger.RepeatCount, (trigger.RepeatInterval / 1000)));

count++;

job = new JobDetail(“job_” + count, schedId, typeof(SimpleQuartzJob));

// ask scheduler to re-Execute this job if it was in progress when

// the scheduler went down…

job.RequestsRecovery = (true);

trigger = new SimpleTrigger(“trig_” + count, schedId, 20, 4000L);

trigger.StartTime = (DateTime.Now.AddMilliseconds(1000L));

sched.ScheduleJob(job, trigger);

_log.Info(string.Format(“{0} will run at: {1} & repeat: {2}/{3}”,
job.FullName, trigger.GetNextFireTime(), trigger.RepeatCount,
trigger.RepeatInterval));

count++;

job = new JobDetail(“job_” + count, schedId, typeof(SimpleQuartzJob));

// ask scheduler to re-Execute this job if it was in progress when

// the scheduler went down…

job.RequestsRecovery = (true);

trigger = new SimpleTrigger(“trig_” + count, schedId, 20, 4500L);

trigger.StartTime = (DateTime.Now.AddMilliseconds(1000L));

sched.ScheduleJob(job, trigger);

_log.Info(string.Format(“{0} will run at: {1} & repeat: {2}/{3}”,
job.FullName, trigger.GetNextFireTime(), trigger.RepeatCount,
trigger.RepeatInterval));

}

// jobs don’t start firing until start() has been called…

_log.Info(“——- Starting Scheduler —————“);

sched.Start();

_log.Info(“——- Started Scheduler —————-“);

_log.Info(“——- Waiting for one hour… ———-“);

Thread.Sleep(TimeSpan.FromHours(1));

_log.Info(“——- Shutting Down ——————–“);

sched.Shutdown();

_log.Info(“——- Shutdown Complete —————-“);

}

public void Run()

{

bool clearJobs = true;

bool scheduleJobs = true;

AdoJobStoreRunner example = new AdoJobStoreRunner();

example.Run(clearJobs, scheduleJobs);

}

}

结束语

Quartz.net 作业调度框架所提供的 API
在少方还表现极佳:既全面强大,又易使。Quartz
可以用于简单的作业点,也堪用于复杂的 Ado.net持久的课业存储和实践。

示例下载 HTTP 
基于 Quartz.net 的示例 (C#代码 )   QuartzBeginnerExample.zip   
324KB  

获取Quartz.net     Download
Quartz:.NET应用程序的开放源码作业调度解决方案

相关文章