分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

Quartz.Net定时任务EF+MVC版的web服务

发布时间:2023-09-06 01:41责任编辑:沈小雨关键词:MVC

    之前项目采用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(); ???????}
 

Quartz.Net定时任务EF+MVC版的web服务

原文地址:https://www.cnblogs.com/Warmsunshine/p/8430451.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved