(02) 任务(Jobs)和触发器(Triggers)

Quart 的 API Quartz API 中的关键接口和类如下: IScheduler—与调度器(scheduler)进行交互的主要 API; IJob—被组件继承和实现,由调度器来执行的接口; IJobDetail—通常被用于定义任务实例; ITrigger—对于给定的任务定义出了它将被执行的时间序列的组件; JobBuilder—通常用来定义(或创建) JobDetail 实例,此实例用于定义任务实例; TriggerBuilder—通常用来定义(或创建)触发器实例。 在本教程中,为了提高可读性以下术语交替使用:IScheduler 和 Scheduler,IJob 和 Job,IJobDetail 和 JobDetail,ITrigger 和 Trigger。 调度器创建后的生命周期是有限的,通过调用调度工厂 (SchedulerFactory) 的 Shutdown() 方法可以关闭调度器。IScheduler 接口创建后即可进行任务和触发器的添加、删除以及列表操作,并且可以执行调度计划相关的其他操作 (例如暂停一个触发器)。然而,就像在《使用Quartz》中所讲的那样,只有在调用 Start() 方法之后调度器才会真正对触发器起作用 (执行任务)。 Quartz 提供的 “builder” 类定义了一种领域专用语言 (DSL,也经常指代“流接口”)。在上一节中已经看到了它的例子,现在我们把它展示在下面: // define the job and tie it to our HelloJob classIJobDetail job = JobBuilder.Create<HelloJob>()    .WithIdentity("myJob", "group1") // name "myJob", group "group1"    .Build();    // Trigger the job to run now, and then every 40 secondsITrigger trigger = TriggerBuilder.Create()    .WithIdentity("myTrigger", "group1")    .StartNow()    .WithSimpleSchedule(x => x        .WithIntervalInSeconds(40)        .RepeatForever())                .Build();    // Tell quartz to schedule the job using our triggersched.scheduleJob(job, trigger); 上面的代码块展示了使用 JobBuilder 创建任务的定义并使用流接口创建了任务 (IJobDetail)。同样,使用针对给定触发器类型的 TriggerBuilder 的流接口和扩展方法创建了触发器。可能的时间计划扩展方法如下: WithCalendarIntervalSchedule WithCronSchedule WithDailyTimeIntervalSchedule WithSimpleSchedule DateBuilder 类包含的很多方法可以让我们很容易地构造特定时间点的 DateTimeOffset 实例 (例如代表下一个偶数小时的时间,换句话说就是如果现在是 9:43:27 那么它将返回 10:00:00)。 任务和触发器 任务就是实现了 IJob 的类,里面只有一个简单的方法: IJob 接口: namespace Quartz{    public interface IJob    {        void Execute(JobExecutionContext context);    }} 当任务的触发器触发以后,调度器的一个工作线程将会调用 Execute(..) 方法。传递到这个方法的 JobExecutionContext 对象提供了一个任务实例,这个实例包含以下运行时环境:一个运行当前任务的调度器的句柄,触发当前任务的触发器的句柄,当前任务的 JobDetail 对象,以及其他几个对象。 调度器加载任务后 Quartz.NET 的客户端 (即我们的应用程序) 会创建 JobDetail 对象。这个对象包含了任务的各种属性设置,以及一个 JobDataMap——它可以用来存储指定任务类型的状态信息。JobDetail 是任务对象的本质,我们会在下一节更详细地讨论它。 触发器用来触发 (或者叫“点火”) 任务的执行操作。当你想要调度一个任务的时候,你需要初始化一个触发器并按照你想要的调度计划来调整它的属性。触发器也可能有一个关联的 JobDataMap,这对于向触发器触发操作指定的任务传递参数来说很有用。Quartz 附带了一些不同的触发器类型,但是通常情况下用的最多的是SimpleTrigger(接口是ISimpleTrigger) 以及 CronTrigger(接口是ICronTrigger)。 如果你需要在指定时间点仅执行一次,或者在指定时间内重复多次并且在每执行前延迟特定时间的任务,使用SimpleTrigger将会很方便。如果你想让触发器有类似于日历的调度计划,CronTrigger将会很合适,例如“每周五下午”或者“每个月第10天的10:15”。 为什么要有任务和触发器?很多任务调试工具都没有将触发器和任务的概念分离。一些组件简单地将任务当作附带一点任务标识的执行时间(或者计划)。还有一些组件很像是Quartz的任务和触发器的结合。但是当我们开发Quartz时, 我们决定将调度计划和在调度计划内将要执行的操作分离开。在我们看来这样做有很多好处。 例如:任务可以独立于触发器创建并存储到任务调度器中,并且可以将多个触发器关联到同一个任务上。另一个松耦合的好处是对于调度器中保留的任务,当与之关联的触发器过期之后,可以不用重新定义这个任务就对它再次进行调度安排;同样的你也可以修改或替换一个触发器而不用重新定义与它关联的任务。 标识 当任务和触发器在Quartz的调度器中注册时就分配了标识主键。任务和触发器的主键(JobKey 和TriggerKey)对于将其组织归并到某个分组并进行分类是非常有用的,例如将任务分为“报表任务”或“维护任务”。组内的任务或触发器的主键名称不能重复,换句话说即任务或触发器的名称以及组名结合在一起就是完整主键(或者标识)。 原文:《Lesson 2: Jobs And Triggers》

Quartz.NET教程:(01) 使用Quartz

使用调度器 (scheduler) 之前要先用 ISchedulerFactory 的一个实现来实例化调度器(scheduler)。一旦调度器实例化完成,则它可以被启动、置于备用模式或者关闭。需要注意的是一旦调度器被关闭,只有重新实例化后才能重新启动它。调度器启动前或者触发器处于暂停状态时,触发器都不会被触发(即任务不会执行)。 下列代码片段演示了实例化并启动一个调度器,并且安排了一个任务以便执行: 使用 Quartz.NET // construct a scheduler factory ISchedulerFactory schedFact = new StdSchedulerFactory(); // get a scheduler IScheduler sched = schedFact.GetScheduler(); sched.Start(); // define the job and tie it to our HelloJob class IJobDetail job = JobBuilder.Create<HelloJob>()                                                        .WithIdentity("myJob", "group1")                                                         .Build(); // Trigger the job to run now, and then every 40 seconds ITrigger trigger = TriggerBuilder.Create()                                                                  .WithIdentity("myTrigger", "group1")                                                                 .StartNow()                                                                 .WithSimpleSchedule(x => x .WithIntervalInSeconds(40)                                                                  .RepeatForever())                                                                  .Build(); sched.ScheduleJob(job, trigger);如你所见,使用Quartz.NET实际上是一个很简单的事。在第2篇教程中将会对 Jobs (任务) 和 Triggers (触发器) 有一个简要了解,以便让初学者能更全面的了解上面这个例子。

Quartz.NET简介及入门指南

Quartz.NET简介 Quartz.NET是一个功能完备的开源调度系统,从最小的应用到大规模的企业系统皆可适用。 Quartz.NET是一个纯净的用C#语言编写的.NET类库,是对非常流行的JAVA开源调度框架 Quartz 的移植。 入门指南 本入门指南包括以下内容: 下载 Quartz.NET 安装 Quartz.NET 根据你的特定项目配置 Quartz 启动一个样例程序 下载和安装 你可以下载 zip 文件或使用 Nuget 程序包。Nuget 程序包只包含 Quartz.NET 运行所必须的二进制文件,zip 文件则包含源码、普通示例程序和 Quartz.NET 的服务端示例程序。 Nuget程序包 没有什么比这个更简单的了。只需要打开 Visual Studio (前提是安装了Nuget)并且从包管理器中添加 Quartz 的引用即可,步骤如下: 在项目的引用上右键单击选择“管理Nuget程序包” 选择“浏览”选项卡,在搜索框中输入“Quartz”并回车 选择 Quartz 并在右侧点击安装即可。 或者用 Nuget 命令行工具,输入如下指令: Install-Package Quartz 配置Quartz.NET 这是很重要的一步,Quartz.NET 是一个配置灵活的类库。有三种提供Quartz.NET配置信息的方式(三种方式之间并不是互相排斥的): 通过提供 NameValueCollection 形式的参数以编程的形式来调度工厂; 通过在标准的应用程序配置文件(形如youapp.exe.config)中添加 quartz-element 相关配置节; 在应用程序根目录中添加 quartz.config 你可以在Quartz.NET 的zip 文件中找到以上三种配置形式的例子。 为了快速地启用示例,一个基本的 quartz.config 应包含如下内容: quartz.scheduler.instanceName = MyScheduler quartz.threadPool.threadCount = 3 quartz.jobStore.type = Quartz.Simpl.RAMJobStore, Quartz 要记得将此文件在 Visual Studio 的文件属性的“复制到输出目录”设置为“总是复制”,否则将会因配置文件缺失而导致程序运行失败。 这个配置文件创建的调度器有以下特性: quartz.scheduler.instanceName - 这个调度器的名称将是 "MyScheduler". quartz.threadPool.threadCount - 调度器将会在线程池中启用3个线程,这意味着最多只能有3个任务同时运行。 quartz.jobStore.type - 所有Quartz的相关数据,例如任务和触发器的详细信息将会保存在内存中(而不是数据库中)。即使你有一个数据库并且想在Quartz中使用它,我也建议你先以内存模式运行Quartz直到你开启了一个使用数据库工作的新次元。 实际上你并不需要去人为指定这些属性,Quartz.NET 拥有健全的默认配置信息。 开始一个示例程序 在你下载并安装 Quartz.NET 之后,便可以开始着手编写一个示例程序了。以下代码包含了一个调度器实例,开启它并随后关闭了它。 Program.cs public class Program{    private static void Main(string[] args)    {        try        {            // Grab the Scheduler instance from the Factory             IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();             // and start it off            scheduler.Start();             // some sleep to show what's happening            Thread.Sleep(TimeSpan.FromSeconds(60));             // and last shut down the scheduler when you are ready to close your program            scheduler.Shutdown();        }        catch (SchedulerException se)        {            Console.WriteLine(se);        }    }} 当你使用 StdSchedulerFactory.GetDefaultScheduler() 获取到一个调度器实例后,由于后台还会有一个活动线程(非守护线程)存在,你的程序将不会通过默认情况关闭直到你调用了 scheduler.Shutdown()。 添加日志 Common.Logging的底层可以通过配置来使用不同的日志框架,即 Enterprise Library, Log4Net 和 NLog。 但是为了使示例保持简单我们选择了最简单的途径,通过代码实现调用 Common.Logging 的基础日志机制将日志输出到控制台。 在 Program.cs 中添加以下内容: Common.Logging.LogManager.Adapter = new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter { Level = Common.Logging.LogLevel.Info};   尝试启动应用程序并添加任务 现在当我们启动应用程序的时候可以得到类似下面的日志输出: 11.1.2014 14:52:04 [INFO] Quartz.Impl.StdSchedulerFactory - Quartz.NET properties loaded from configuration file 'c:\ConsoleApplication1\bin\Debug\quartz.config' 11.1.2014 14:52:04 [INFO] Quartz.Impl.StdSchedulerFactory - Using default implementation for object serializer 11.1.2014 14:52:04 [INFO] Quartz.Impl.StdSchedulerFactory - Using default implementation for ThreadExecutor 11.1.2014 14:52:04 [INFO] Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl 11.1.2014 14:52:04 [INFO] Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.2.1.400 created. 11.1.2014 14:52:04 [INFO] Quartz.Simpl.RAMJobStore - RAMJobStore initialized. 11.1.2014 14:52:04 [INFO] Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.1.400) 'MyScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'Quartz.Simpl.SimpleThreadPool' - with 3 threads. Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered. 11.1.2014 14:52:04 [INFO] Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'MyScheduler' initialized 11.1.2014 14:52:04 [INFO] Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 2.2.1.400 11.1.2014 14:52:04 [INFO] Quartz.Core.QuartzScheduler - Scheduler MyScheduler_$_NON_CLUSTERED started.   我们创建一个简单的 HelloJob 任务来测试功能,这个任务将输出问候信息到控制台: public class HelloJob : IJob {         public void Execute(IJobExecutionContext context)               {                         Console.WriteLine("Greetings from HelloJob!");                } } 我们来做一些更有趣的事情,在 Start() 之后线程休眠之前我们加入一些代码: // define the job and tie it to our HelloJob classIJobDetail job = JobBuilder.Create<HelloJob>()    .WithIdentity("job1", "group1")    .Build(); // Trigger the job to run now, and then repeat every 10 secondsITrigger trigger = TriggerBuilder.Create()    .WithIdentity("trigger1", "group1")    .StartNow()    .WithSimpleSchedule(x => x        .WithIntervalInSeconds(10)        .RepeatForever())    .Build(); // Tell quartz to schedule the job using our triggerscheduler.ScheduleJob(job, trigger); 下面是一个完整的控制台程序内容: using System;using System.Threading; using Quartz;using Quartz.Impl;using Quartz.Job; namespace ConsoleApplication1{    public class Program    {        private static void Main(string[] args)        {            try            {                Common.Logging.LogManager.Adapter = new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter {Level = Common.Logging.LogLevel.Info};                 // Grab the Scheduler instance from the Factory                 IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();                 // and start it off                scheduler.Start();                 // define the job and tie it to our HelloJob class                IJobDetail job = JobBuilder.Create<HelloJob>()                    .WithIdentity("job1", "group1")                    .Build();                 // Trigger the job to run now, and then repeat every 10 seconds                ITrigger trigger = TriggerBuilder.Create()                    .WithIdentity("trigger1", "group1")                    .StartNow()                    .WithSimpleSchedule(x => x                        .WithIntervalInSeconds(10)                        .RepeatForever())                    .Build();                 // Tell quartz to schedule the job using our trigger                scheduler.ScheduleJob(job, trigger);                 // some sleep to show what's happening                Thread.Sleep(TimeSpan.FromSeconds(60));                 // and last shut down the scheduler when you are ready to close your program                scheduler.Shutdown();            }            catch (SchedulerException se)            {                Console.WriteLine(se);            }             Console.WriteLine("Press any key to close the application");            Console.ReadKey();        }    }     public class HelloJob : IJob    {        public void Execute(IJobExecutionContext context)        {            Console.WriteLine("Greetings from HelloJob!");        }    }}
友情链接:Smart Testing