Quartz.NET實現作業調度

来源:http://www.cnblogs.com/best/archive/2017/10/13/7658573.html
-Advertisement-
Play Games

一、Quartz.NET介紹 Quartz.NET是一個強大、開源、輕量的作業調度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於winform和asp.net應用中。它靈活而不複雜。你能夠用它來為執行一個作業而創建簡單的或複雜的作業調度。它有很多特征 ...


一、Quartz.NET介紹

Quartz.NET是一個強大、開源、輕量的作業調度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於winform和asp.net應用中。它靈活而不複雜。你能夠用它來為執行一個作業而創建簡單的或複雜的作業調度。它有很多特征,如:資料庫支持,集群,插件,支持cron-like表達式等等。

通俗說它的功能是:比如說我想每天晚上2點讓程式或網站執行某些代碼,或者每隔5秒種我想查看是否有新的任務要處理等。

官網:http://www.quartz-scheduler.net/

源碼:https://github.com/quartznet/quartznet

示例:http://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html

其實Quartz是一個完全由java編寫的開源作業調度框架,Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,它可以與J2EE與J2SE應用程式相結合也可以單獨使用。Quartz可以用來創建簡單或為運行十個,百個,甚至是好幾萬個Jobs這樣複雜的程式。而Quartz.Net與NPOI一樣是一個DoNet平臺下的對應版本。如果您使用Java直接訪問這裡就好了http://www.quartz-scheduler.org/

二、依賴框架

引入框架的方法非常簡單你可以直接用nuget管理包也可以在項目中添加引用:

2.1、使用Nuget添加引用

2.1.0、創建一個項目

創建一個新項目,可以是ASP.NET MVC,WebForms,Winforms等多種.Net項目,這裡使用的是VS2013,創建了一個MVC項目:

2.1.1、安裝Nuget

新版本的Visual Studio預設情況是安裝了Nuget的,如Visual Studio2015,但如果沒有安裝,打開VS菜單“工具”->"擴展與更新"

在擴展與更新中搜索“nuget”,可以新安裝或卸載後升級:

2.1.2、修改Nuget鏡像

為解決國內訪問NuGet伺服器速度不穩定的問題建議你最好選擇一些鏡像伺服器,這樣可以加速下載。

在Visual Studio中的添加方法是:打開“工具”->“選項”菜單

在左側菜單中找到“NuGet包管理器”

點擊右上角的加號,添加兩個鏡像,這些地址可以上網搜索,我使用的是如下兩個:

https://nuget.cnblogs.com/v3/index.json

http://api.nuget.org/v3/index.json

設置一下順序就OK了。

2.1.3、使用nuget安裝Quartz.NET

點擊“工具”->"NuGet包管理器"->“程式包管理器控制台”

輸入安裝包的命令:

Install-Package Quartz

安裝結果如下:

此時包管理器中就下載了需要的程式集與相關文件,程式中也添加了引用。

 

2.2、手動引用

當然如果您不願意使用nuget也可以下載到Quartz後直接引用,可以在本文尾部下載到框架。

框架下載地址:鏈接: https://pan.baidu.com/s/1slDM5JJ 密碼: 9x5m

三、應用框架

假定我現在想當前的MVC應用每隔5秒鐘向C:\Quartz.txt文件中記錄當前時間

因為這是一個Web應用,我想網站一啟動時就開始該項工作,這裡我們需要打開Global.asax,將代碼寫在Application_Start方法中

3.1、定義要執行的任務

定義一個類,實現Quartz.IJob介面,實現方法Execute,TimeJob.cs文件的代碼如下:

using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1
{
    public class TimeJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            //向c:\Quartz.txt寫入當前時間並換行
            System.IO.File.AppendAllText(@"c:\Quartz.txt", DateTime.Now+Environment.NewLine);
        }
    }
}

3.2、創建一個調度器

調度器負責管理與控制任務的執行,在Global.asax文件的Application_Start方法中添加如下代碼:

            //調度器
            IScheduler scheduler;
            //調度器工廠
            ISchedulerFactory factory;

            //創建一個調度器
            factory = new StdSchedulerFactory();
            scheduler = factory.GetScheduler();
            scheduler.Start();

3.3、創建一個任務對象

這個任務對象就是我們將要執行的工作,job1是名稱,group1是組名。

            //2、創建一個任務
            IJobDetail job = JobBuilder.Create<TimeJob>().WithIdentity("job1", "group1").Build();

3.4、創建一個觸發器

觸發器定義了什麼時間任務開始或每隔多久執行一次。

            //3、創建一個觸發器
            //DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("trigger1", "group1")
                .WithCronSchedule("0/5 * * * * ?")     //5秒執行一次
                //.StartAt(runTime)
                .Build();

3.5、將任務與觸發器添加到調度器中並執行

            //4、將任務與觸發器添加到調度器中
            scheduler.ScheduleJob(job, trigger);
            //5、開始執行
            scheduler.Start();

3.6、應用關閉時結束任務

當網站關閉時結束正在執行的工作,在Global.asax中的Application_End方法中添加如下代碼:

        protected void Application_End(object sender, EventArgs e)
        {
            //   在應用程式關閉時運行的代碼
            if (scheduler != null)
            {
                scheduler.Shutdown(true);
            }
        }

shutdown方法中的參數true的意思為:是否等待任務的完成再結束。

3.7、運行結果

3.8、Global.asax中的完整代碼

using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace MvcApplication1
{
    public class MvcApplication : System.Web.HttpApplication
    {
        //調度器
        IScheduler scheduler;
        //調度器工廠
        ISchedulerFactory factory;
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            //1、創建一個調度器
            factory = new StdSchedulerFactory();
            scheduler = factory.GetScheduler();
            scheduler.Start();

            //2、創建一個任務
            IJobDetail job = JobBuilder.Create<TimeJob>().WithIdentity("job1", "group1").Build();

            //3、創建一個觸發器
            //DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("trigger1", "group1")
                .WithCronSchedule("0/5 * * * * ?")     //5秒執行一次
                //.StartAt(runTime)
                .Build();

            //4、將任務與觸發器添加到調度器中
            scheduler.ScheduleJob(job, trigger);
            //5、開始執行
            scheduler.Start();
        }

        protected void Application_End(object sender, EventArgs e)
        {
            //   在應用程式關閉時運行的代碼
            if (scheduler != null)
            {
                scheduler.Shutdown(true);
            }
        }
    }
}

四、框架說明

看官方的示例、源碼或幫助文檔可以瞭解更多的使用方法,官方幫助的地址是:https://www.quartz-scheduler.net/documentation/index.html

4.1、Quartz的cron表達式

cron表達式就是用於設定時間的一個字元串,在前面的代碼中我們就用到了,如下所示:

            //3、創建一個觸發器
            //DateTimeOffset runTime = DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity("trigger1", "group1")
                .WithCronSchedule("0/5 * * * * ?")     //5秒執行一次
                //.StartAt(runTime)
                .Build();

官方英文介紹:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/crontrigger.html

cron expressions 整體上還是非常容易理解的,只有一點需要註意:"?"號的用法,看下文可以知道“?”可以用在 day of month 和 day of week中,他主要是為瞭解決如下場景,如:每月的1號的每小時的31分鐘,正確的表達式是:* 31 * 1 * ?,而不能是:* 31 * 1 * *,因為這樣代表每周的任意一天。

/*
由7段構成:秒 分 時 日 月 星期 年(可選)

"-" :表示範圍  MON-WED表示星期一到星期三
"," :表示列舉 MON,WEB表示星期一和星期三
"*" :表是“每”,每月,每天,每周,每年等
"/" :表示增量:0/15(處於分鐘段裡面) 每15分鐘,在0分以後開始,3/20 每20分鐘,從3分鐘以後開始
"?" :只能出現在日,星期段裡面,表示不指定具體的值
"L" :只能出現在日,星期段裡面,是Last的縮寫,一個月的最後一天,一個星期的最後一天(星期六)
"W" :表示工作日,距離給定值最近的工作日
"#" :表示一個月的第幾個星期幾,例如:"6#3"表示每個月的第三個星期五(1=SUN...6=FRI,7=SAT)

如果Minutes的數值是 '0/15' ,表示從0開始每15分鐘執行

如果Minutes的數值是 '3/20' ,表示從3開始每20分鐘執行,也就是‘3/23/43’
*/

官方示例:

表達式解釋
0 0 12 * * ? 每天中午12點觸發
0 15 10 ? * * 每天上午10:15觸發
0 15 10 * * ? 每天上午10:15觸發
0 15 10 * * ? * 每天上午10:15觸發
0 15 10 * * ? 2005 2005年的每天上午10:15觸發
0 * 14 * * ? 在每天下午2點到下午2:59期間的每1分鐘觸發
0 0/5 14 * * ? 在每天下午2點到下午2:55期間的每5分鐘觸發
0 0/5 14,18 * * ? 在每天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發
0 0-5 14 * * ? 在每天下午2點到下午2:05期間的每1分鐘觸發
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44觸發
0 15 10 ? * MON-FRI 周一至周五的上午10:15觸發
0 15 10 15 * ? 每月15日上午10:15觸發
0 15 10 L * ? 每月最後一日的上午10:15觸發
0 15 10 L-2 * ? 每個月的第二天到最後一天的上午10:15觸發
0 15 10 ? * 6L 每月的最後一個星期五上午10:15觸發
0 15 10 ? * 6L 每個月最後一個星期五上午10時15分觸發
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最後一個星期五上午10:15觸發
0 15 10 ? * 6#3 每月的第三個星期五上午10:15觸發
0 0 12 1/5 * ? 每月每隔5天下午12點(中午)觸發, 從每月的第一天開始
0 11 11 11 11 ? 每11月11日上午11時11分觸發

4.2、其它幫助

請查看幫助文檔、示例或上網搜索,:),後面有空再補充吧

4.3、IIS應用程式池自動回收問題的有效解決辦法

IIS可以設置定時自動回收,預設回收是1740分鐘,也就是29小時。IIS自動回收相當於伺服器IIS重啟,應用程式池記憶體清空,所有數據被清除,相當於IIS重啟,在度量快速開發平臺伺服器端,為了減小資料庫負擔,記憶體中暫存了很多信息,不適合頻繁的回收,因為回收會造成伺服器端所有存在記憶體中的數據丟失,如果沒有及時保存到資料庫中,可能導致程式出現問題。而如果系統使用高峰時期,並不適合回收,回收可能導致幾十秒IIS無響應,對於正在工作的人員來說,是一種很不好的體驗,會以為是網路或者掉線等問題。

如果IIS重啟則Global.asax中的方法將被再次執行,如果不想IIS自動重啟可以使用如下的設置:

IIS應用程式池回收,找到相應的應用程式池並點擊高級設置,就可以看到回收的相關設置

發生配置更改時禁止回收:如果為True,應用程式池在發生配置更改時將不會回收。

固定時間間隔(分鐘):超過設置的時間後,應用程式池回收,為0意味著應用程式池不會按固定間隔回收。系統預設設置的時間是1740(29小時)。

禁用重疊回收:如果為true,將發生應用程式池回收,以便在創建另一個工作進程之前退出現有工作進程。

請求限制:應用程式池在回收之前可以處理的最大請求數。如果值為0,則表示應用程式池可以處理的請求數沒有限制。

生成回收事件日誌條目:每發生一次指定的回收事件時便產生一個事件日誌條目。

更多參考:http://www.cnblogs.com/Fishwood/p/3602041.html

五、總結

1、實現定時任務的方法有很多,如果非常簡單的話直接使用系統內置的Timer,Scheduler,Cache都是可以達到的,但要註意GC回收的問題,一般會定義成靜態的。

2、本文只是非常粗淺的介紹了一下零配置的方法,您也可以選擇使用XML配置的方式替代部分的硬編碼。

六、下載

示例下載 密碼: 9x5m

框架下載 密碼: 9x5m


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

-Advertisement-
Play Games
更多相關文章
  • 根據可變性的規則,只有介面和委托可以標記可變性。且只有類型參數為引用類型時才可以利用可變性。 不變性:泛型類型的參數不能改變,這表示一個創建一個MyInterface<String>類型的對象時,賦值給它的只能是MyInterface<String>類型 逆變性:泛型的類型參數可以從一個類變成它的派 ...
  • .NET 實用擴展方法(持續更新...) 1. 字元串轉換為可空數值類型(int, long, float...類似) /// /// 將字元串轉換成32位整數,轉換失敗返回null /// /// 轉換的字元串 /// 轉換之後的整數,或null public static int? TryPar ...
  • foreach: continue;:退出本次迴圈 break;:退出迴圈 return;:退出迴圈 List.Foreach: return;:退出本次迴圈 小結:list.Foreach中不能退出迴圈,foreach中的return;和List.Foreach中的return;用法不同 ...
  • ActiveMQ .NET類庫 ActiveMQ是一種開源的,實現了JMS規範的,面向消息(MOM)的中間件,為應用程式提供高效的、可擴展的、穩定的和安全的企業級消息通信。 0. 準備 使用Nuget管理控制台安裝最新版 Apache.NMS.ActiveMQ PM Install Package ...
  • 回到目錄 TransactionScope是.net平臺基於的分散式事務組件,它預設為本地事務,同時當系統有需要時可以自動提升為分散式事務,而對系統的前提是要開啟MSDTC服務,必要時需要在資料庫伺服器與應用伺服器之間添加hosts的映射,這些在之前已經寫過很多文章了,在這裡不再說了。 之前對Tra ...
  • 什麼是大端和小端 Big-Endian和Little-Endian的定義如下:1) Little-Endian就是低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端。2) Big-Endian就是高位位元組排放在記憶體的低地址端,低位位元組排放在記憶體的高地址端。舉一個例子,比如數字0x12 34 ...
  • lock 關鍵字將語句塊標記為臨界區,方法是獲取給定對象的互斥鎖,執行語句,然後釋放該鎖。 lock語句根本使用的就是Monitor.Enter和Monitor.Exit,也就是說lock(this)時執行Monitor.Enter(this),大括弧結束時執行Monitor.Exit(this). ...
  • 閱讀目錄 背景 代碼描述 越分析越黑暗 結語 一、背景 這個標題起的有點標題黨的嫌疑[捂臉],這個事情的原委是這樣的,有個Web API的站點在本地使用Release模式Run的時候出現問題,但是使用Debug模式則不會。通過打日誌定位到問題在如下的這個代碼這裡: 理論上,會有一次請求進入到2中,但 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...