zoukankan      html  css  js  c++  java
  • C# 基于Quartz.NET实现任务调度并部署Windows服务

    放在最前面->Timer

    在没有引入第三方开源的定时调度框架之前,我们处理一些简单的定时任务同时都是使用Timer类, DotNet中的Timer类有三个,分别位于不同的命名空间下,分别是:

        ①.位于System.Windows.Forms里,即定时器控件,不过多介绍了

        ②.位于System.Threading.Timer类里 (重点介绍)

        ③.位于System.Timers.Timer类里 (不介绍)

      下面重点介绍第二种,位于Threading下面的Timer类,观察其源码,发现有多种构造函数,我们重点介绍其中的一种。

     分享一段代码:2秒后开启该线程,然后每隔4s调用一次。

    //2秒后开启该线程,然后每隔4s调用一次
      System.Threading.Timer timer = new System.Threading.Timer((n) =>
      {
                 //书写业务逻辑
                Console.WriteLine("---------------------执行系统健康检查任务,所有指标均正常。执行时间:{0}------------------- ", DateTime.Now);
       }, "1", 2000, 4000);     

    分析总结:上面的代码显而易见,只能控制:延迟多久开始执行,每隔多久执行一次,至于执行多少次、什么时间关闭均无法实现,更不用说处理一些复杂的时间间隔了,所以Timer类仅仅适合处理对时间要求非常简单的定时任务。

    所以我们引入了Quartz.Net框架,接下来请看下面。

    Quartz.NET介绍

    官方几句话:Quarzt.Net框架是一个强大、开源、轻量的作业调度框架。它灵活而不复杂。你能够用它来为执行一个作业而创建简单的或复杂的作业调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等。

    具体有多么好用,还是得你用了才能知道。

    Quartz.NET用途

    可以定时去做一些事情(每天两点发送邮件;每隔30分钟给用户推送一些消息等)等等。我目前用的比较浅,如果用的比较深之后后续补充。

    搭建环境

    1、VS2017

    2、Quartz.dll(版本:3.0.7.0)=》作用是实现任务调度

    3、Topshelf.dll(版本:Topshelf)=》创建Windows服务

    Quartz.NET入门使用

    创建一个控制台应用程序,如下图:

    通过NuGet包引入Quartz.dll和Topshelf.dll,引用方式如下图:

     然后编码:

    需要创建两个类文件

      QuartzHelper:使用Quartz框架,编写任务和触发器加入到作业调度池;

      Job:编写你需要执行的任务;

       /// <summary>
        /// 任务调度帮助类
        /// </summary>
        public class QuartzHelper
        {
            #region 公共变量
            /// <summary>
            /// 任务调度器
            /// </summary>
            public readonly IScheduler Scheduler;#endregion
    
            #region 构造函数
            /// <summary>
            /// 构造函数
            /// </summary>
            public QuartzHelper()
            {
                var properties = new NameValueCollection();
                // 设置线程池
                properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
                //设置线程池的最大线程数量
                properties["quartz.threadPool.threadCount"] = "5";
                //设置作业中每个线程的优先级
                properties["quartz.threadPool.threadPriority"] = ThreadPriority.Normal.ToString();
                // 远程输出配置
                properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
                properties["quartz.scheduler.exporter.port"] = "555";  //配置端口号
                properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
                properties["quartz.scheduler.exporter.channelType"] = "tcp"; //协议类型
                //创建一个工厂
                var schedulerFactory = new StdSchedulerFactory(properties);
                //启动
                Scheduler = schedulerFactory.GetScheduler().Result;
                //1、开启调度
                Start();
    
                //室内环境Http推送功能
                AddJobAndTrigger();
            }
            #endregion
    
            #region MyRegion
            /// <summary>
            /// 开启任务
            /// </summary>
            public void Start()
            {
                Scheduler.Start();
            }
    
            /// <summary>
            /// 关闭任务
            /// </summary>
            public void Stop()
            {
                //true:表示该Sheduler关闭之前需要等现在所有正在运行的工作完成才能关闭
                //false:表示直接关闭
                Scheduler.Shutdown(true);
            }
    
            /// <summary>
            /// 暂停调度
            /// </summary>
            public void Pause()
            {
                Scheduler.PauseAll();
            }
    
            /// <summary>
            /// 继续调度
            /// </summary>
            public void Continue()
            {
                Scheduler.ResumeAll();
            }
            #endregion
    
            #region 不同时间方式执行任务
            /// <summary>
            /// 时间间隔执行任务
            /// </summary>
            /// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
            /// <param name="seconds">时间间隔(单位:秒)</param>
            public async Task<bool> ExecuteByInterval<T>(int seconds) where T : IJob
            {
                //2、创建工作任务
                IJobDetail job = JobBuilder.Create<T>().Build();
    
                //3、创建触发器
                ITrigger trigger = TriggerBuilder.Create()
               .StartNow()
               .WithSimpleSchedule(
                    x => x.WithIntervalInSeconds(seconds)
                    //x.WithIntervalInMinutes(1)
                    .RepeatForever())
               .Build();
    
                //4、将任务加入到任务池
                await Scheduler.ScheduleJob(job, trigger);
                return true;
            }/// <summary>
            /// 指定时间执行任务
            /// </summary>
            /// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
            /// <param name="cronExpression">cron表达式,即指定时间点的表达式</param>
            public async Task<bool> ExecuteByCron<T>(string cronExpression) where T : IJob
            {
                //2、创建工作任务
                IJobDetail job = JobBuilder.Create<T>().Build();
                //3、创建触发器
                ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                .StartNow()
                .WithCronSchedule(cronExpression)
                .Build();
                //4、将任务加入到任务池
                await Scheduler.ScheduleJob(job, trigger);
                return true;
            }
            #endregion
    
            #region 添加任务和触发器
            /// <summary>
            /// 添加任务和触发器
            /// </summary>
            public void AddJobAndTrigger()
            {
            //根据时间间隔执行任务
            ExecuteByInterval<Job>(20).Wait();
         } 

        #endregion
    }

      Job必须要继承IJob,并且显式的实现Execute方法,然后在Execute方法里面编写你想要实现的功能;

        public class Job : IJob
        {
            #region 任务执行
            Task IJob.Execute(IJobExecutionContext context)
            {
                Task task = null;
                try
                {
              LogHelper.Log($"推送成功=>这里就放你想做的事务", "TaskScheduling");
             } 
         catch (Exception ex)
         {
          LogHelper.Log($"推送失败=>{ex.Message.ToString()}", "TaskScheduling");
           }
           return task;
         }
         #endregion
       }

    引入Topshelf.dll,使用HostFactory.Run创建Windows服务。这端代码放在控制台应用程序Program类的Main方法里。

    //设置事务,开启触发器
    HostFactory.Run(x =>
    {
            x.Service<QuartzHelper>(s =>
           {
                 s.ConstructUsing(name => new QuartzHelper());
                 s.WhenStarted(tc => tc.Start());
                 s.WhenStopped(tc => tc.Stop());
           });
    
           x.RunAsLocalSystem();
           x.SetDescription("QuartzJob任务定时发送");
           x.SetDisplayName("QuartzJob");
           x.SetServiceName("QuartzJob");
           x.EnablePauseAndContinue();
    });

    这样一个基于Quartz.Net的作业任务调度框架就搭建完成了。GOOD!!!!

    感谢大佬们的前车。才有我现在这么顺利的结果。再次十分感谢。

    @奔跑的路上:https://www.cnblogs.com/yaopengfei/category/1164016.html

    @wuzh:https://www.cnblogs.com/wzh5959/p/11678938.html

    @奔跑的路上,大佬的文章很优秀,你如果静下心来,仔细阅读,你会发现少走很多弯路。而且每篇篇幅很短,阅读没压力。

    小菜一只,成长路上,接受批评,也接受您的点点点(点赞呀)。

    手动微笑~

  • 相关阅读:
    算法竞赛入门经典第一章习题解答
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    机器狗组装费用 南邮NOJ 1076 优先权队列
    【HDOJ】2604 Queuing
    【HDOJ】1208 Pascal's Travels
    【HDOJ】4857 逃生
    【HDOJ】2510 符号三角形
  • 原文地址:https://www.cnblogs.com/pukua/p/12035380.html
Copyright © 2011-2022 走看看