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.mzph.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;忽略它。 安装完成…