SQL Server详细讲解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应用程序的开放源码作业调度解决方案

相关文章