Quartz+TopShelf實現Windows服務作業調度

来源:http://www.cnblogs.com/frozenzhang/archive/2016/04/29/5443778.html
-Advertisement-
Play Games

Quartz:首先我貼出來了兩段代碼(下方),可以看出,首先根據配置文件(quartz.config),包裝出一個Quartz.Core.QuartzScheduler instance,這是一個調度器,調度各個任務項(Jobs)的執行。這個調度器可以被Start、被Shutdown、被PauseA ...


  Quartz:首先我貼出來了兩段代碼(下方),可以看出,首先會根據配置文件(quartz.config),包裝出一個Quartz.Core.QuartzScheduler

instance,這是一個調度器,調度各個任務項(Jobs)的執行。這個調度器可以被Start、被Shutdown、被PauseAll、被ResumeAll,這對應

了windows服務的開啟、停止、暫停、恢復。當啟動服務,我就調用調度器的Start(),停止服務我就調用調度器的Shutdown()方法。

namespace QTDemo
{
    public class ServiceRunner : ServiceControl, ServiceSuspend
    {
        private readonly IScheduler scheduler;

        public ServiceRunner()
        {
            scheduler = StdSchedulerFactory.GetDefaultScheduler();
        }

        public bool Start(HostControl hostControl)
        {
            scheduler.Start();
            return true;
        }
// 摘要: 
    //     An implementation of Quartz.ISchedulerFactory that does all of it's work
    //     of creating a Quartz.Core.QuartzScheduler instance based on the contents
    //     of a properties file.
    public class StdSchedulerFactory : ISchedulerFactory
    {
        public const string AutoGenerateInstanceId = "AUTO";
        public const string ConfigurationSectionName = "quartz";
        public const string DefaultInstanceId = "NON_CLUSTERED";
        public const string PropertiesFile = "quartz.config";

  那TopShelf又扮演了什麼樣的角色呢

  這是一個宿主服務的框架。和ServiceBase、ServiceInstaller那一套的目的一樣,都是用來創建Windows服務的。

  

項目示例

1、新建項目控制台應用程式‘QTDemo’

 

2、從NuGet安裝‘Quartz’,‘Topshelf’,‘Topshelf.Log4Net’ 

1 <?xml version="1.0" encoding="utf-8"?>
2 <packages>
3   <package id="Common.Logging" version="3.3.1" targetFramework="net45" />
4   <package id="Common.Logging.Core" version="3.3.1" targetFramework="net45" />
5   <package id="log4net" version="2.0.5" targetFramework="net45" />
6   <package id="Quartz" version="2.3.3" targetFramework="net45" />
7   <package id="Topshelf" version="3.3.1" targetFramework="net45" />
8   <package id="Topshelf.Log4Net" version="3.3.1" targetFramework="net45" />
9 </packages>

 

3、定義一個Job(一個任務項),繼承Quartz.IJob

 1 using Quartz;
 2 namespace QTDemo.QuartzJobs
 3 {
 4     public sealed class TestJob : IJob
 5     {
 6         public void Execute(IJobExecutionContext context)
 7         {
 8             CommonHelper.AppLogger.InfoFormat("TestJob測試");
 9 
10         }
11     }
12 }
13  

 

4、配置(新建)quartz.config、quartz_jobs.xml

quartz.config可直接使用,不用修改

 1 # You can configure your scheduler in either <quartz> configuration section
 2 # or in quartz properties file
 3 # Configuration section has precedence
 4 
 5 quartz.scheduler.instanceName = QuartzTest
 6 
 7 # configure thread pool info
 8 quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
 9 quartz.threadPool.threadCount = 10
10 quartz.threadPool.threadPriority = Normal
11 
12 # job initialization plugin handles our xml reading, without it defaults are used
13 quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
14 quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
15 
16 # export this server to remoting context
17 #quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
18 #quartz.scheduler.exporter.port = 555
19 #quartz.scheduler.exporter.bindName = QuartzScheduler
20 #quartz.scheduler.exporter.channelType = tcp
21 #quartz.scheduler.exporter.channelName = httpQuartz
View Code

quartz_jobs.xml根據實際的Job項修改

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!-- This file contains job definitions in schema version 2.0 format -->
 3 
 4 <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
 5 
 6   <processing-directives>
 7     <overwrite-existing-data>true</overwrite-existing-data>
 8   </processing-directives>
 9 
10   <schedule>
11 
12     <!--TestJob測試 任務配置 -->
13     <job>
14       <name>TestJob</name>
15       <group>Test</group>
16       <description>TestJob測試</description>
17       <job-type>QTDemo.QuartzJobs.TestJob,QTDemo</job-type>
18       <durable>true</durable>
19       <recover>false</recover>
20     </job>
21     <trigger>
22       <cron>
23         <name>TestJobTrigger</name>
24         <group>Test</group>
25         <job-name>TestJob</job-name>
26         <job-group>Test</job-group>
27         <!-- 從start-time起,每5s執行一次IJob.Execute -->
28         <start-time>2012-01-22T00:00:00+08:00</start-time>
29         <cron-expression>0/5 * * * * ?</cron-expression>
30       </cron>
31     </trigger>
32     
33   </schedule>
34 </job-scheduling-data>

 

5、創建服務

入口:

 1 using System;
 2 using System.IO;
 3 using Topshelf;
 4 
 5 namespace QTDemo
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config"));
12 
16             HostFactory.Run(x =>
17             {
18                 x.UseLog4Net();
19 
20                 x.Service<ServiceRunner>();
21 
22                 x.RunAsLocalSystem();
23 
24                 x.SetDescription("Quartz+TopShelf實現Windows服務作業調度的一個示例Demo");
25                 x.SetDisplayName("QuartzTopShelfDemo服務");
26                 x.SetServiceName("QuartzTopShelfDemoService");
27 
28                 x.EnablePauseAndContinue();
29 
30             });
31         }
32     }
33 }

ServiceRunner.cs

 1 using Quartz;
 2 using Quartz.Impl;
 3 using Topshelf;
 4 
 5 namespace QTDemo
 6 {
 7     public class ServiceRunner : ServiceControl, ServiceSuspend
 8     {
 9         private readonly IScheduler scheduler;
10 
11         public ServiceRunner()
12         {
13             scheduler = StdSchedulerFactory.GetDefaultScheduler();
14         }
15 
16         public bool Start(HostControl hostControl)
17         {
18             scheduler.Start();
19             return true;
20         }
21 
22         public bool Stop(HostControl hostControl)
23         {
24             scheduler.Shutdown(false);
25             return true;
26         }
27 
28         public bool Continue(HostControl hostControl)
29         {
30             scheduler.ResumeAll();
31             return true;
32         }
33 
34         public bool Pause(HostControl hostControl)
35         {
36             scheduler.PauseAll();
37             return true;
38         }
39 
40     }
41 }

 

log4net配置文件,可直接使用

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <configSections>
 4     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
 5   </configSections>
 6 
 7   <log4net>
 8     <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
 9       <!--日誌路徑-->
10       <param name= "File" value= "Log\"/>
11       <!--是否是向文件中追加日誌-->
12       <param name= "AppendToFile" value= "true"/>
13       <!--log保留天數-->
14       <param name= "MaxSizeRollBackups" value= "10"/>
15       <!--日誌文件名是否是固定不變的-->
16       <param name= "StaticLogFileName" value= "false"/>
17       <!--日誌文件名格式為:2008-08-31.log-->
18       <param name= "DatePattern" value= "yyyy-MM-dd&quot;.read.log&quot;"/>
19       <!--日誌根據日期滾動-->
20       <param name= "RollingStyle" value= "Date"/>
21       <layout type="log4net.Layout.PatternLayout">
22         <param name="ConversionPattern" value="%date{HH:mm:ss,fff} %-5p-%m%n" />
23       </layout>
24     </appender>
25 
26     <!-- 控制台前臺顯示日誌 -->
27     <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
28       <mapping>
29         <level value="ERROR" />
30         <foreColor value="Red, HighIntensity" />
31       </mapping>
32       <mapping>
33         <level value="Info" />
34         <foreColor value="Green" />
35       </mapping>
36       <layout type="log4net.Layout.PatternLayout">
37         <conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" />
38       </layout>
39 
40       <filter type="log4net.Filter.LevelRangeFilter">
41         <param name="LevelMin" value="Info" />
42         <param name="LevelMax" value="Fatal" />
43       </filter>
44     </appender>
45 
46     <root>
47       <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
48       <level value="all" />
49       <appender-ref ref="ColoredConsoleAppender"/>
50       <appender-ref ref="RollingLogFileAppender"/>
51     </root>
52     
53   </log4net>
54 </configuration>
View Code 

 

6、quartz.config、quartz_jobs.xml、log4net.config都設置成‘始終複製’

 

7、直接F5,調試,發現TestJob每5s執行一次

 

8、安裝成Windows服務

用Release編一個版本

然後用命令行安裝服務

服務面板里可以找到此服務

啟動之,查看日誌文件,服務運行正常

23:23:52,171 INFO -Configuration Result:
[Success] Name QuartzTopShelfDemoService
[Success] DisplayName QuartzTopShelfDemo服務
[Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo
[Success] ServiceName QuartzTopShelfDemoService
23:23:52,185 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014
23:23:52,194 ERROR-The QuartzTopShelfDemoService service can only be installed as an administrator
23:25:54,758 INFO -Configuration Result:
[Success] Name QuartzTopShelfDemoService
[Success] DisplayName QuartzTopShelfDemo服務
[Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo
[Success] ServiceName QuartzTopShelfDemoService
23:25:54,772 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014
23:25:54,781 DEBUG-Attempting to install 'QuartzTopShelfDemoService'
23:25:54,901 INFO -Installing QuartzTopShelfDemo服務 service
23:25:55,123 DEBUG-Opening Registry
23:25:55,123 DEBUG-Service path: "E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release\QTDemo.exe"
23:25:55,123 DEBUG-Image path: "E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release\QTDemo.exe"  -displayname "QuartzTopShelfDemo服務" -servicename "QuartzTopShelfDemoService"
23:25:58,357 DEBUG-Closing Registry
23:28:10,442 INFO -Configuration Result:
[Success] Name QuartzTopShelfDemoService
[Success] DisplayName QuartzTopShelfDemo服務
[Success] Description Quartz+TopShelf實現Windows服務作業調度的一個示例Demo
[Success] ServiceName QuartzTopShelfDemoService
23:28:10,455 INFO -Topshelf v3.3.154.0, .NET Framework v4.0.30319.34014
23:28:10,649 DEBUG-Started by the Windows services process
23:28:10,649 DEBUG-Running as a service, creating service host.
23:28:10,651 INFO -Starting as a Windows service
23:28:10,654 DEBUG-[Topshelf] Starting up as a windows service application
23:28:10,657 INFO -[Topshelf] Starting
23:28:10,658 DEBUG-[Topshelf] Current Directory: E:\DotNetProject\Y2016\QTDemo\QTDemo\bin\Release
23:28:10,658 DEBUG-[Topshelf] Arguments: 
23:28:10,940 INFO -[Topshelf] Started
23:28:10,988 INFO -TestJob測試
23:28:15,000 INFO -TestJob測試
23:28:20,000 INFO -TestJob測試

 

  附:源碼下載

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 嵌入式軟體開發中,雖然很多的開發工具已經支持C++的開發,但是因為有時考慮運行效率和編程習慣,還是有很多人喜歡用C來開發嵌入式軟體。Miro Samek說:“我在開發現場發現,很多嵌入式軟體開發者(絕大多數是電子工程師)都有工作背景而且他們常常不喜歡用C++。”【1】面向對象編程(OOP)是一種方法... ...
  • :介紹 在shell4.0之後支持普通數組和關聯數組,普通數組只能使用整數作為索引,關聯數組可以使用字元串作為索引。 普通數組 普通數組的定義方法有如下兩種,註意數組的索引是從0開始 方法1:值之間是使用空格隔開 array=(1 2 3 4 5) 方法2:直接定義索引-值的方法,其實該方法相當於是 ...
  • 在使用硬碟之前必須對其分區進行格式化,並掛載: ...
  • 本人最近正在學習調試技術,此處對棧溢出做一些總結。 gdb的基本使用就不多扯了。 主要針對發行在外的release版本的軟體出現問題時的調試。 我發現,只要源碼相同,在gdb的命令行下或者開啟gdb時,指定的可執行文件是debug版的,是可以顯示出正確的符號信息的。這個大大地提高了調試效率。 一般來 ...
  • u8 是 unsigned char u16 是 unsigned short u32 是 unsigned int ...
  • IronMan之裝飾者 前言 上一篇的文章我們講到要給"IronMan"配備"武器",並且還使用了"武器",效果還是不錯的,對於多種環境、多種攻擊方式的"武器"使用,我們已經掌握了。 有的朋友沒有看過上一篇文章,那也沒關係,此篇的重點不會涉及到上一篇的內容。 好吧,廢話不多說,直接進入正題, 這裡簡 ...
  • ...
  • 【問】xml的標準形式是: <Root> <Name>John</Name> <Age>16</Age> </Root> 現在假如是一個字元串的形式—— <Root><Name>John</Name><Age>16</Age></Root> 請教如何對該字元串格式化,以便成為標準的xml文件格式? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...