正如标题所示,文章主要是围绕Quartz.Net作业调度框架话题展开的,内容出自博主学习官方Examples的学习心得与体会,文中难免会有错误之处,还请指出得以指教。

在百度一下搜索Quartz.Net,可以知道Quartz.Net是Net版本的任务调度框架,是一个从java移植过来的Net版本的开源框架,在作业调度方面提供了很好的灵活性而不牺牲简单,能够为执行一个作业而创建简单的或复杂的调度,目前版本支持数据库,集群,插件配置,支持cron表达式等等

Quartz Enterprise Schedulder .Net

官方下载地址:

http://sourceforge.net/projects/quartznet/files/quartznet/

官方文档:

http://www.quartz-scheduler.net/documentation/index.html

到此我们大概了解了一下Quartz.Net是什么,在继续讨论相关Quartz之前,我们先来思考并解决一个问题。

假设程序有这么一个需求,在一定的时间间隔里,轮询做一种操作或者任务,我想首先当然可以这么实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Process();
        }

        public static void Process()
        {
            DateTime now = DateTime.Now;
            //1.0 读取web.config中的定时器的时间间隔
            string timespan = System.Configuration.ConfigurationManager.AppSettings["timer"];
            double dtimespan = 0;
            int repeat = 0;
            if (double.TryParse(timespan, out dtimespan) == false)
            {
                dtimespan = 10;
            }
            Console.WriteLine("Info[{0}]任务初始化完成.....",DateTime.Now);
            while (true)
            {
                try
                {
                    //1.0 开启定时器
                    if ((DateTime.Now - now).TotalSeconds >= dtimespan)
                    {
                        Console.WriteLine("任务正在执行.....这是第{0}次",repeat+1);
                        //开始调度任务
                        SayHello();
                        repeat++;
                        Console.WriteLine("任务执行完成.....");
                        //重置now
                        now = DateTime.Now;
                    }
                    //预留cpu的线程切换时间
                    System.Threading.Thread.Sleep(2000);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error:{0}",ex.ToString());
                }
            }
        }
        public static void SayHello() {
            Console.WriteLine("Info:[{0}] Hello, everyone, I'm YZR.",DateTime.Now);
        }
    }
}
Test

运行的结果如下:

Info[2016/4/23 星期六 上午 12:01:57]任务初始化完成.....
任务正在执行.....这是第1次
Info:[2016/4/23 星期六 上午 12:02:17] Hello, everyone, I'm YZR.
任务执行完成.....
任务正在执行.....这是第2次
Info:[2016/4/23 星期六 上午 12:02:37] Hello, everyone, I'm YZR.
任务执行完成.....
任务正在执行.....这是第3次
Info:[2016/4/23 星期六 上午 12:02:57] Hello, everyone, I'm YZR.
任务执行完成.....
任务正在执行.....这是第4次
Info:[2016/4/23 星期六 上午 12:03:17] Hello, everyone, I'm YZR.
任务执行完成.....


上面的程序完成的功能是每20秒会在控制台中打印SayHello的信息,并且会记录任务重复执行的次数。

其实这就是一个简单的任务调度的过程,接下来演示使用Quartz.Net如何实现这个功能:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.Logging;

namespace Quartz.Examples
{
    public class SayHelloJob : IJob
    {

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

        /// <summary> 
        /// 作业或者任务需要一个无参构造函数来进行初始化
        /// </summary>
        public SayHelloJob()
        {
        }
        #region IJob 成员

        public void Execute(IJobExecutionContext context)
        {
            
            _log.Info(string.Format("Hello, everyone, I'm YZR. - {0}", System.DateTime.Now.ToString("r")));
        }

        #endregion
    }
}
SayHelloJob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Quartz.Impl;
using Common.Logging;

namespace Quartz.Examples
{
    public class SayHelloExample:IExample
    {
        #region IExample 成员

        public string Name
        {
            get { return GetType().Name; }
        }

        public void Run()
        {
            ILog log = LogManager.GetLogger(typeof(SimpleExample));

            log.Info("------- 初始化中 ----------------------");
            //首先,我们必须得到一个参考的调度程序
            ISchedulerFactory sf = new StdSchedulerFactory();
            IScheduler sched = sf.GetScheduler();

            log.Info("------- 初始化完成 -----------");


            // 得到一个轮询的触发时间
            DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);

            log.Info("------- 调度作业  -------------------");

            // 定义一个作业并且绑定到指定的Job类中
            IJobDetail job = JobBuilder.Create<SayHelloJob>()
                .WithIdentity("job1", "group1")
                .Build();

            // 作业的触发器会在下一次轮询的时机中执行作业
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("trigger1", "group1")
                .StartAt(runTime).WithSimpleSchedule(x=>x.WithIntervalInSeconds(20).RepeatForever())
                .Build();

            //根据作业和触发器添加到调度队列
            sched.ScheduleJob(job, trigger);
            log.Info(string.Format("{0} will run at: {1}", job.Key, runTime.ToString("r")));

            //启动调度程序
            sched.Start();
            log.Info("------- 开始调度 -----------------");

            
            log.Info("------- 等待2分钟.... -------------");

            //睡眠65秒
            Thread.Sleep(TimeSpan.FromSeconds(120));

            // shut down the scheduler
            log.Info("------- 正在关闭调度作业 ---------------------");
            sched.Shutdown(true);
            log.Info("------- 关闭调度作业完成 -----------------");
        }

        #endregion
    }
}
SayHelloExample
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quartz.Util;
using System.Reflection;

namespace Quartz.Examples
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //反射得到当前运行程序集
                Assembly asm = Assembly.GetExecutingAssembly();
                //获取所有类
                Type[] types = asm.GetTypes();

                IDictionary<int, Type> typeMap = new Dictionary<int, Type>();
                int counter = 1;

                Console.WriteLine("Select example to run: ");
                List<Type> typeList = new List<Type>();
                //循环遍历当前运行程序集的所有类
                foreach (Type t in types)
                {
                    //将实现了IExample接口的类加入到typeList集合中
                    if (new List<Type>(t.GetInterfaces()).Contains(typeof(IExample)))
                    {
                        typeList.Add(t);
                    }
                }

                typeList.Sort(new TypeNameComparer());

                //循环将序号 类名  加入到typeMap字典中
                foreach (Type t in typeList)
                {
                    string counterString = string.Format("[{0}]", counter).PadRight(4);
                    Console.WriteLine("{0} {1} {2}", counterString, t.Namespace.Substring(t.Namespace.LastIndexOf(".") + 1), t.Name);
                    typeMap.Add(counter++, t);
                }

                Console.WriteLine();
                Console.Write("> ");
                //选择要运行的类的序号
                int num = Convert.ToInt32(Console.ReadLine());
                //获取该类的Type
                Type eType = typeMap[num];
                //得到该类的实例
                IExample example = ObjectUtils.InstantiateType<IExample>(eType);
                //运行Run()
                example.Run();
                Console.WriteLine("Example run successfully.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error running example: " + ex.Message);
                Console.WriteLine(ex.ToString());

            }
            Console.Read();
        }
        /// <summary>
        /// 用于排序的比较器
        /// </summary>
        public class TypeNameComparer : IComparer<Type>
        {
            public int Compare(Type t1, Type t2)
            {
                if (t1.Namespace.Length > t2.Namespace.Length)
                {
                    return 1;
                }

                if (t1.Namespace.Length < t2.Namespace.Length)
                {
                    return -1;
                }

                return t1.Namespace.CompareTo(t2.Namespace);
            }
        }
    }
}
Main
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Quartz.Examples
{
    /// <summary>
    /// Interface for examples.
    /// </summary>
    /// <author>Marko Lahma (.NET)</author>
    public interface IExample
    {
        string Name
        {
            get;
        }

        void Run();
    }
}
IExample.cs

 

运行结果如下:

2016-04-23 00:37:43,679 [1] INFO  Quartz.Impl.StdSchedulerFactory.Instantiate(D:
\Quartz.NET-2.3.2\src\Quartz\Impl\StdSchedulerFactory.cs:1021) - Quartz scheduler'DefaultQuartzScheduler' initialized
2016-04-23 00:37:43,681 [1] INFO  Quartz.Impl.StdSchedulerFactory.Instantiate(D:
\Quartz.NET-2.3.2\src\Quartz\Impl\StdSchedulerFactory.cs:1023) - Quartz scheduler version: 2.3.2.0
2016-04-23 00:37:43,683 [1] INFO  Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:29) - ------- 初始化完成 -----------
2016-04-23 00:37:43,684 [1] INFO  Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:35) - ------- 调度作业  -------------------
2016-04-23 00:37:43,697 [1] INFO  Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:50) - group1.job1 will run at: Fri, 22 Apr 2016 16:38:00 GMT
2016-04-23 00:37:43,697 [1] INFO  Quartz.Core.QuartzScheduler.Start(D:\Quartz.NET-2.3.2\src\Quartz\Core\QuartzScheduler.cs:441) - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
2016-04-23 00:37:43,697 [1] INFO  Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:54) - ------- 开始调度 -----------------
2016-04-23 00:37:43,697 [1] INFO  Quartz.Examples.SayHelloExample.Run(C:\Users\A
dministrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloExample.cs:57) - ------- 等待2分钟.... -------------
2016-04-23 00:38:00,044 [DefaultQuartzScheduler_Worker-1] INFO  Quartz.Examples.SayHelloJob.Execute(C:\Users\Administrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloJob.cs:25)

- Hello, everyone, I'm YZR. - Sat, 23 Apr 2016 00:38:00 GMT
2016-04-23 00:38:20,000 [DefaultQuartzScheduler_Worker-2] INFO  Quartz.Examples.SayHelloJob.Execute(C:\Users\Administrator\Desktop\Quatorz\Quartz.Examples\Quartz.Examples\SayHelloJob.cs:25)

- Hello, everyone, I'm YZR. - Sat, 23 Apr 2016 00:38:20 GMT

 

效果同样也是每20秒运行一次作业,但这只是Quartz.Net框架一个简单的任务调度演示,它拥有着更多复杂有用的功能以及特点,我们在下篇会正式进入Quartz.Net的使用话题。

posted on 2016-04-23 00:55  巴夫巴夫  阅读(261)  评论(0编辑  收藏  举报