Quartz.Net定時任務EF+MVC版的web服務

? ? 之前項目采用JAVA 的 Quartz 進行定時服調度務處理程序,目前在.NET下面使用依然可以完成相同的工作任務,其實什么語言不重要,關鍵是我們要學會利用語言實現價值。它是一個簡單的執行任務計劃的組件,基本包括這三部分:Job(作業)、Trigger(觸發器)、scheduler(調度器)。

? ? ?? 1.Job 作業:需要在任務計劃中執行的具體邏輯操作

??????? 2.Trigger 觸發器:需要什么時間什么規則來去執行Job 作業

??????? 3.scheduler 調度器 :將Job 和 Trigger 注冊到 scheduler 調度器中,主要負責協調Job、Trigger 的運行

.NET可以做成服務端方式也可以做成web端處理,本方法是采用web的方式處理,話不多說直接上干活。在這里借鑒了別人的方式但是別人的有些很多漏洞和錯誤,我也進行了拋磚引玉加以完善。

首先先創建一個新項目,新建一個類庫JobLibrary項目庫:

一個Job 創建一個實例類,創建兩個實例類一個是UpdateCompleteJob.cs、UpdateAutoCancelStateJob.cs (之所以創建兩個Job是為了能方便大家了解這個組件可以同時執行多個任務)

一:UpdateCompleteJob.cs 代碼如下:

namespace JobLibrary
{// quartz.net 禁止并發執行DisallowConcurrentExecution是禁止相同JobDetail同時執行,而不是禁止多個不同JobDetail同時執行。建議加上該特性,防止由于任務執行時間太長,長時間占用資源,導致其它任務堵塞。
    [DisallowConcurrentExecution]public class UpdateCompleteJob : IJob{TRA_BargainOrder_Test ExpressModel;/// <summary>///在Job 中我們必須實現IJob接口中的Execute 這個方法,才能正確的使用Job/// </summary>public async Task Execute(IJobExecutionContext context){using (var _DbContext = new DefaultDbContext()){//var tarorder = new TRA_BargainOrder_Test()//{//    BargainOrderCode="12345688899",//    OrderStatus=1//};//_DbContext.TRA_BargainOrders.Add(tarorder);////保存記錄,返回受影響的行數//int record = _DbContext.SaveChanges();//Console.WriteLine("添加{0}記錄成功", record);var query = _DbContext.TRA_BargainOrders.Where(c => c.OrderStatus == (int)EnumHelper.OrderStatus.Sended);//var query = _DbContext.TRA_BargainOrders.Where(c => c.OrderStatus == (int)EnumHelper.OrderStatus.Sended//                                && c.PayStatus == (int)EnumHelper.PayStatus.Paid).OrderBy(c => c.CreateTime).ToList().Take(20);foreach (var item in query){if (!string.IsNullOrEmpty(item.ExpressCode)){//根據快遞單號獲取快遞訂單信息try{ExpressModel = await _DbContext.TRA_BargainOrders.SingleOrDefaultAsync(s => s.ExpressCode == item.ExpressCode);}catch (Exception e){new Exception(e.Message);}//確定 已簽收  修改訂單狀態 已完成if (ExpressModel.OrderStatus ==1&& ExpressModel.ischeck == 1){var order = _DbContext.TRA_BargainOrders.FirstOrDefault(c => c.BargainOrderCode == item.BargainOrderCode);// var order = _DbContext.Set<TRA_BargainOrder_Test>().FirstOrDefault(c => c.BargainOrderCode == item.BargainOrderCode);order.OrderStatus = (int)EnumHelper.OrderStatus.Over;order.FlowStatus = (int)EnumHelper.FlowStatus.Over;order.UpdateTime = DateTime.Now;_DbContext.TRA_BargainOrders.Attach(order);_DbContext.Entry(order).State = EntityState.Modified;_DbContext.TRA_BargainOrders.AddOrUpdate(order);}}}//保存數據庫不能放到循環中操作 try{_DbContext.SaveChanges();}catch (Exception E){ throw new Exception(E.Message); }}}}
}

二:UpdateAutoCancelStateJob.cs 代碼如下:

namespace JobLibrary
{//在Quartz.Net中,一個job(作業)即為一個類,為了讓job能在Quartz.Net的體系中執行,我們必須實現Quartz.Net提供的IJob接口的Execute方法,如本例所實現的IJob接口UpdateAutoCancelStateJob類:
    [DisallowConcurrentExecution]public class UpdateAutoCancelStateJob : IJob{public async Task Execute(IJobExecutionContext context){using (var _DbContext = new DefaultDbContext()){var order = await _DbContext.TRA_BargainOrders.FirstOrDefaultAsync(c => c.OrderStatus == (int)EnumHelper.OrderStatus.UnSend && c.PayStatus == (int)EnumHelper.PayStatus.UnPaid);if (order!=null){if (DateDiff(DateTime.Now, order.CreateTime) > 30){order.OrderStatus = (int)EnumHelper.OrderStatus.Cancel;order.FlowStatus = (int)EnumHelper.FlowStatus.Cancel;order.UpdateTime = DateTime.Now;_DbContext.SaveChanges();}}}}//計算時間差的方法private int DateDiff(DateTime DateTime1, DateTime DateTime2){TimeSpan tss = Convert.ToDateTime(DateTime1) - Convert.ToDateTime(DateTime2);int dateDiff = Convert.ToInt32(tss.TotalMinutes);return dateDiff;}}
}

以下是web啟動項目下的

三:設置Trigger 觸發器,在實際中我是將Trigger和Job 直接注冊到 scheduler 調度器中;就是需要將類庫生成的DLL 拷貝到你的需要執行的項目的文件中

觸發器的JobManage代碼如下:

 public class JobManage{private static ISchedulerFactory sf = new StdSchedulerFactory();//調度器private static IScheduler scheduler;/// <summary>/// 讀取調度器配置文件的開始時間/// </summary>//public static void StartScheduleFromConfig()public static async void StartScheduleFromConfigAsync(){string currentDir = AppDomain.CurrentDomain.BaseDirectory;try{XDocument xDoc = XDocument.Load(Path.Combine(currentDir, "JobScheduler.config"));var jobScheduler = from x in xDoc.Descendants("JobScheduler") select x;var jobs = jobScheduler.Elements("Job");XElement jobDetailXElement, triggerXElement;//獲取調度器scheduler = await sf.GetScheduler();//聲明觸發器
                CronTriggerImpl cronTrigger;foreach (var job in jobs){//加載程序集joblibaray  Assembly ass = Assembly.LoadFrom(Path.Combine(currentDir, job.Element("DllName").Value));//獲取任務名字jobDetailXElement = job.Element("JobDetail");//獲取任務觸發的時間triggerXElement = job.Element("Trigger");JobDetailImpl jobDetail = new JobDetailImpl(jobDetailXElement.Attribute("job").Value,jobDetailXElement.Attribute("group").Value,ass.GetType(jobDetailXElement.Attribute("jobtype").Value));if (triggerXElement.Attribute("type").Value.Equals("CronTrigger")){cronTrigger = new CronTriggerImpl(triggerXElement.Attribute("name").Value,triggerXElement.Attribute("group").Value,triggerXElement.Attribute("expression").Value);//添加定時器await scheduler.ScheduleJob(jobDetail, cronTrigger);}}//開始執行定時器await scheduler.Start();}catch (Exception E){throw new Exception(E.Message);}}/// <summary>/// 關閉定時器/// </summary>public static void ShutDown(){if (scheduler != null && !scheduler.IsShutdown){scheduler.Shutdown();}}/// <summary>/// 從Scheduler?移除當前的Job,修改Trigger???/// </summary>/// <param name="jobExecution"></param>/// <param name="time"></param>public static void ModifyJobTime(IJobExecutionContext jobExecution, String time){scheduler = jobExecution.Scheduler;ITrigger trigger = jobExecution.Trigger;IJobDetail jobDetail = jobExecution.JobDetail;if (trigger != null){CronTriggerImpl ct = (CronTriggerImpl)trigger;//?移除當前進程的Job?????
                scheduler.DeleteJob(jobDetail.Key);//?修改Trigger?????ct.CronExpressionString = time;Console.WriteLine("CronTrigger?getName?" + ct.JobName);//?重新調度jobDetail?????
                scheduler.ScheduleJob(jobDetail, ct);}}}

四:配置文件,主要是控制任務執行的時間和Job 的加載 JobScheduler.config

<?xml version="1.0" encoding="utf-8"?>
<configuration><!--配置文件,主要是控制任務執行的時間和Job 的加載   配置中重要的幾個屬性 <DllName>JobLibrary.dll</DllName> dll的名字 ;jobtype 屬性是dll名字+實例類的名字;expression 這個是設置執行的時間--><JobScheduler><Job Description="作業1"><DllName>JobLibrary.dll</DllName><JobDetail job="test1" group="test1Group" jobtype="JobLibrary.UpdateCompleteJob" /><Trigger name="test1" group="test1Group" type="CronTrigger" expression="0 0/50 * * * ?" />  <!--0 0/10 * * * ? 10分鐘--> </Job><Job Description="作業2"><DllName>JobLibrary.dll</DllName><JobDetail job="test2" group="test2Group" jobtype="JobLibrary.UpdateAutoCancelStateJob" /><Trigger name="test2" group="test2Group" type="CronTrigger" expression="0/10 * * * * ?" /> <!--0/10 * * * * ? 10秒-->  <!-- 每天凌晨1點執行一次:0 0 1 * * ? -->  <!--每天凌晨1點30分執行一次:0 30 1 * * ?--> <!--每天的0點、13點、18點、21點都執行一次:0 0 0,13,18,21 * * ?  --><!-- "0 0/5 14,18 * * ?" ? ?每天14點或18點中,每5分鐘觸發--></Job></JobScheduler><system.web><compilation debug="true" targetFramework="4.6.1" /><httpRuntime targetFramework="4.6.1" /></system.web></configuration>

五:需要將scheduler 調度器注冊到程序中;在程序中Global.asax.cs 中文件中添加注冊,在這里啟動執行任務

 //需要將scheduler 調度器注冊到程序中;在程序中Global.asax.cs 中文件中添加注冊,在這里啟動執行任務。protected void Application_Start(){AreaRegistration.RegisterAllAreas();FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);//執行的任務
            JobManage.StartScheduleFromConfigAsync();}//當網站關閉時結束正在執行的工作protected void Application_End(object sender, EventArgs e){//   在應用程序關閉時運行的代碼
            JobManage.ShutDown();}

?六:至此可以啟動服務完成定時調度處理任務了

?

轉載于:https://www.cnblogs.com/Warmsunshine/p/8430451.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250962.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250962.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250962.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jquery --- 多選下拉框的移動(穿梭框)

效果如下: 幾個注意地方: 1.多選下拉框需要添加 multiple 2.獲取選中的元素KaTeX parse error: Expected EOF, got # at position 3: (#?id option:selec…(#id option:not(:selected)) 下面是代碼的各個部分實現, 方便引用,最后是總體代碼,方便理解 添加選中到右邊: // …

ES6-24 生成器與迭代器的應用

手寫生成器 先done再false&#xff0c;不然index就提前了一步1 var arr [1,2] function generator(arr){var i 0;return{next(){var done i > arr.length ? true : false,value done ? undefined : arr[i];return {value : value,done : done} }} } var gen gener…

1013 B. And

鏈接 [http://codeforces.com/contest/1013/problem/B] 題意 給你一個n和x,再給n個數&#xff0c;有一種操作用x&a[i]取代&#xff0c;a[i],問使其中至少兩個數相同&#xff0c;要多少次操作&#xff0c;如果不能輸出-1. 思路 x&a[i],無論&多少次&#xff0c;a[i]都…

jquery --- 收縮兄弟元素

點擊高亮的收縮兄弟元素. 思路: 1.點擊的其實是tr.(類為parent) 2.toggleClass可以切換樣式 3.slblings(’.class’).toggle 可以根據其類來進行隱藏顯示 代碼如下: <!DOCTYPE html> <html> <head> <meta charset"utf-8"><style>.pa…

Webpack基礎

path.resolve // 只要以/開頭&#xff0c;就變為絕對路徑 // ./和直接寫效果相同 var path require("path") //引入node的path模塊path.resolve(/foo/bar, ./baz) // returns /foo/bar/baz path.resolve(/foo/bar, baz) // returns /foo/bar/baz path.res…

(php)實現萬年歷

1 <?php2 //修改頁面編碼3 header("content-type:text/html;charsetutf-8");4 5 //獲取當前年6 $year$_GET[y]?$_GET[y]:date(Y);7 8 //獲取當年月9 $month$_GET[m]?$_GET[m]:date(m); 10 11 //獲取當前月多少天 12 $daysdate(t,strtotime("{$year}-{$m…

LeetCode:二叉樹相關應用

LeetCode&#xff1a;二叉樹相關應用 基礎知識 617.歸并兩個二叉樹 題目 Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge them into a new …

ubuntu16.04 python3.5 opencv的安裝與卸載(轉載)

轉載https://blog.csdn.net/qq_37541097/article/details/79045595 Ubuntu16.04 自帶python2.7和python3.5兩個版本&#xff0c;默認為python2.7&#xff0c;我使用的是3.5&#xff0c;所以首先將默認的python版本改為3.5. 在終端輸入下列指令&#xff1a; sudo update-alterna…

Webpack進階(一) tree shaking與不同mode

Tree Shaking 生產環境去除沒有使用到的內容&#xff08;開發環境沒有刪除&#xff0c;會影響調試&#xff09;只支持ESM規范&#xff08;靜態引入&#xff0c;編譯時引入&#xff09;&#xff0c;不支持CJS&#xff08;動態引入&#xff0c;執行時引入&#xff09; // webpa…

jquery --- 網頁選項卡

點擊,不同的tab_menu,顯示不同的tab_box 注意點: 1.獲取ul下,當前li的編號. $(‘div ul li’).index(this) 2.顯示ul下編號為$index的li -> $(‘ul li’).eq($index) <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <style&g…

Webpack進階(二)代碼分割 Code Splitting

源代碼index.js里包含2部分① 業務邏輯代碼 1mb② 引入&#xff08;如lodash包&#xff09;的代碼 1mb若更新了業務邏輯代碼&#xff0c;但在瀏覽器運行時每次都下載2mb的index.js顯然不合理&#xff0c;第三方包是不會變的 手動拆分 webpack.base.js entry: {main: path.re…

5177. 【NOIP2017提高組模擬6.28】TRAVEL (Standard IO)

Description Input Output Solution 有大佬說&#xff1a;可以用LCT做。&#xff08;會嗎&#xff1f;不會&#xff09; 對于蒟蒻的我&#xff0c;只好用水法&#xff08;3s&#xff0c;不虛&#xff09;。 首先選出的泡泡怪一定是連續的一段 L&#xff0c; R 然后 L 一定屬于蟲…

python 3.x 爬蟲基礎---http headers詳解

python 3.x 爬蟲基礎 python 3.x 爬蟲基礎---http headers詳解 python 3.x 爬蟲基礎---Urllib詳解 python 3.x 爬蟲基礎---Requersts,BeautifulSoup4&#xff08;bs4&#xff09; python 3.x 爬蟲基礎---正則表達式 前言  上一篇文章 python 爬蟲入門案例----爬取某站上海租房…

Webpack進階(三)

懶加載 lazy loading 用到的時候才加載vue 首屏不加載index.js const oBtn document.getElementById(j-button) oBtn.onclick async function () {const div await createElement()document.body.appendChild(div) } async function createElement() {const { default: _ …

P2634 [國家集訓隊]聰聰可可

鏈接&#xff1a;https://www.luogu.org/problemnew/show/P2634 題目描述 聰聰和可可是兄弟倆&#xff0c;他們倆經常為了一些瑣事打起來&#xff0c;例如家中只剩下最后一根冰棍而兩人都想吃、兩個人都想玩兒電腦&#xff08;可是他們家只有一臺電腦&#xff09;……遇到這種問…

算法 --- 快慢指針判斷鏈表是否有環

解題思路: 分別設置2個指針(s,q)指向鏈表的頭部,s每次指向下面一個(s s.next),q每次指向下面2個(q q.next.next). 如果存在環,q總會在某一時刻追上s /*** Definition for singly-linked list.* function ListNode(val) {* this.val val;* this.next null;* }*//**…

APP拉起小程序

結論&#xff1a;APP可以喚起小程序&#xff0c;前提是APP開發者在微信開放平臺帳號下申請移動應用&#xff0c;通過審核并關聯小程序&#xff0c;參考如下&#xff1a; 準備工作: APP開發者認證微信開放平臺 https://kf.qq.com/faq/170824URbmau170824r2uY7j.html APP開發者…

node --- 使用nrm改變npm的源

說明: 1.nrm只是單純的提供了幾個常用的下載包的URL地址,方便我們再使用npm裝包是 很方便的進行切換. 2.nrm提供的cnpm 和通過 cnpm裝包是2個不同的東西(使用cnpm install必須先安裝cnpm -> npm install -g cnpm) 安裝nrm: // linux $ [sudo] npm install --global nrm// w…

MySQL教程(三)—— MySQL的安裝與配置

1 安裝MySQL 打開附件中的文件&#xff08;分別對應電腦系統為32/64位&#xff09;。點next。 三個選項&#xff0c;分別對應典型安裝、自定義安裝和完全安裝&#xff0c;在此選擇典型安裝&#xff08;初學者&#xff09;。 點install。 廣告&#xff0c;忽略它。 安裝完成…