当前位置:首页 > 操作系统 > Windows

C# 基于Quartz.NET实现任务调度并部署Windows服务

放在最前面->Timer

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

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

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

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

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

技术分享图片

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

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

分析总结:上面的代码显而易见,只能控制:延迟多久开始执行,每隔多久执行一次,至于执行多少次、什么时间关闭均无法实现,更不用说处理一些复杂的时间间隔了,所以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:编写你需要执行的任务;

            <span>   ///</span>
            <span><summary></span>
            <span>///</span>
            <span> 任务调度帮助类
    </span>
            <span>///</span>
            <span></summary></span>
            <span>public</span>
            <span>class</span>
            <span> QuartzHelper
    {
        </span>
            <span>#region</span> 公共变量
        <span>///</span><span><summary></span><span>///</span><span> 任务调度器
        </span><span>///</span><span></summary></span><span>public</span><span>readonly</span><span> IScheduler Scheduler;</span><span>#endregion</span><span>#region</span> 构造函数
        <span>///</span><span><summary></span><span>///</span><span> 构造函数
        </span><span>///</span><span></summary></span><span>public</span><span> QuartzHelper()
        {
            </span><span>var</span> properties = <span>new</span><span> NameValueCollection();
            </span><span>//</span><span> 设置线程池</span>
            properties[<span>"</span><span>quartz.threadPool.type</span><span>"</span>] = <span>"</span><span>Quartz.Simpl.SimpleThreadPool, Quartz</span><span>"</span><span>;
            </span><span>//</span><span>设置线程池的最大线程数量</span>
            properties[<span>"</span><span>quartz.threadPool.threadCount</span><span>"</span>] = <span>"</span><span>5</span><span>"</span><span>;
            </span><span>//</span><span>设置作业中每个线程的优先级</span>
            properties[<span>"</span><span>quartz.threadPool.threadPriority</span><span>"</span>] =<span> ThreadPriority.Normal.ToString();
            </span><span>//</span><span> 远程输出配置</span>
            properties[<span>"</span><span>quartz.scheduler.exporter.type</span><span>"</span>] = <span>"</span><span>Quartz.Simpl.RemotingSchedulerExporter, Quartz</span><span>"</span><span>;
            properties[</span><span>"</span><span>quartz.scheduler.exporter.port</span><span>"</span>] = <span>"</span><span>555</span><span>"</span>;  <span>//</span><span>配置端口号</span>
            properties[<span>"</span><span>quartz.scheduler.exporter.bindName</span><span>"</span>] = <span>"</span><span>QuartzScheduler</span><span>"</span><span>;
            properties[</span><span>"</span><span>quartz.scheduler.exporter.channelType</span><span>"</span>] = <span>"</span><span>tcp</span><span>"</span>; <span>//</span><span>协议类型
            </span><span>//</span><span>创建一个工厂</span><span>var</span> schedulerFactory = <span>new</span><span> StdSchedulerFactory(properties);
            </span><span>//</span><span>启动</span>
            Scheduler =<span> schedulerFactory.GetScheduler().Result;
            </span><span>//1、</span><span>开启调度</span><span>            Start();

            </span><span>//</span><span>室内环境Http推送功能</span><span>            AddJobAndTrigger();
        }
        </span><span>#endregion</span><span>#region</span> MyRegion
        <span>///</span><span><summary></span><span>///</span><span> 开启任务
        </span><span>///</span><span></summary></span><span>public</span><span>void</span><span> Start()
        {
            Scheduler.Start();
        }

        </span><span>///</span><span><summary></span><span>///</span><span> 关闭任务
        </span><span>///</span><span></summary></span><span>public</span><span>void</span><span> Stop()
        {
            </span><span>//</span><span>true:表示该Sheduler关闭之前需要等现在所有正在运行的工作完成才能关闭
            </span><span>//</span><span>false:表示直接关闭</span>
            Scheduler.Shutdown(<span>true</span><span>);
        }

        </span><span>///</span><span><summary></span><span>///</span><span> 暂停调度
        </span><span>///</span><span></summary></span><span>public</span><span>void</span><span> Pause()
        {
            Scheduler.PauseAll();
        }

        </span><span>///</span><span><summary></span><span>///</span><span> 继续调度
        </span><span>///</span><span></summary></span><span>public</span><span>void</span><span> Continue()
        {
            Scheduler.ResumeAll();
        }
        </span><span>#endregion</span><span>#region</span> 不同时间方式执行任务
        <span>///</span><span><summary></span><span>///</span><span> 时间间隔执行任务
        </span><span>///</span><span></summary></span><span>///</span><span><typeparam name="T"></span><span>任务类,必须实现IJob接口</span><span></typeparam></span><span>///</span><span><param name="seconds"></span><span>时间间隔(单位:秒)</span><span></param></span><span>public</span><span>async</span> Task<<span>bool</span>> ExecuteByInterval<T>(<span>int</span> seconds) <span>where</span><span> T : IJob
        {
            </span><span>//</span><span>2、创建工作任务</span>
            IJobDetail job = JobBuilder.Create<T><span>().Build();

            </span><span>//</span><span>3、创建触发器</span>
            ITrigger trigger =<span> TriggerBuilder.Create()
           .StartNow()
           .WithSimpleSchedule(
                x </span>=><span> x.WithIntervalInSeconds(seconds)
                </span><span>//</span><span>x.WithIntervalInMinutes(1)</span><span>                .RepeatForever())
           .Build();

            </span><span>//</span><span>4、将任务加入到任务池</span><span>await</span><span> Scheduler.ScheduleJob(job, trigger);
            </span><span>return</span><span>true</span><span>;
        }</span><span>///</span><span><summary></span><span>///</span><span> 指定时间执行任务
        </span><span>///</span><span></summary></span><span>///</span><span><typeparam name="T"></span><span>任务类,必须实现IJob接口</span><span></typeparam></span><span>///</span><span><param name="cronExpression"></span><span>cron表达式,即指定时间点的表达式</span><span></param></span><span>public</span><span>async</span> Task<<span>bool</span>> ExecuteByCron<T>(<span>string</span> cronExpression) <span>where</span><span> T : IJob
        {
            </span><span>//</span><span>2、创建工作任务</span>
            IJobDetail job = JobBuilder.Create<T><span>().Build();
            </span><span>//</span><span>3、创建触发器</span>
            ICronTrigger trigger =<span> (ICronTrigger)TriggerBuilder.Create()
            .StartNow()
            .WithCronSchedule(cronExpression)
            .Build();
            </span><span>//</span><span>4、将任务加入到任务池</span><span>await</span><span> Scheduler.ScheduleJob(job, trigger);
            </span><span>return</span><span>true</span><span>;
        }
        </span><span>#endregion</span><span>#region</span> 添加任务和触发器
        <span>///</span><span><summary></span><span>///</span><span> 添加任务和触发器
        </span><span>///</span><span></summary></span><span>public</span><span>void</span><span> AddJobAndTrigger()
        {</span>
            <span>//根据时间间隔执行任务</span>
        
            <span>        ExecuteByInterval<Job><span>(20).Wait();</span></span>
        
            <span>     } <br /></span>
            <span>     #endregion<br /></span>
            <span>}</span>
        

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

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

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

            <span>//</span>
            <span>设置事务,开启触发器</span>
HostFactory.Run(x =><span>
{
        x.Service</span><QuartzHelper>(s =><span>
       {
             s.ConstructUsing(name </span>=> <span>new</span><span> QuartzHelper());
             s.WhenStarted(tc </span>=><span> tc.Start());
             s.WhenStopped(tc </span>=><span> tc.Stop());
       });

       x.RunAsLocalSystem();
       x.SetDescription(</span><span>"Quartz</span><span>Job任务定时发送</span><span>"</span><span>);
       x.SetDisplayName(</span><span>"</span><span>QuartzJob</span><span>"</span><span>);
       x.SetServiceName(</span><span>"</span><span>QuartzJob</span><span>"</span><span>);
       x.EnablePauseAndContinue();
});</span>

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

 

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

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

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

 

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

 

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

手动微笑~

原文:https://www.cnblogs.com/pukua/p/12035380.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐