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 ==&& ExpressModel.ischeck == )
{
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) > )
{
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服务的更多相关文章
- 处理畅捷通的T+ 12.0版,web服务无故自动停止的问题
用了几个月的畅捷通T+ 12.0版,一直都挺正常,但最近这两周,出现了好几次web服务自动停止的情况,今天抽空仔细看了Windows的日志,发现在半夜2点左右,TPlusProWebService12 ...
- "轻"量级 Java Web 服务框架漫谈
博文太长了, 还是先说下概要: 框架"轻量"与否可以从两方面来看待: 1) 框架本身的体量 - 例如小 jar 无依赖的苗条框架; 2) 用户使用框架是否获得各种便利而无阻隔(&q ...
- .Net Core3.1 + EF Core + LayUI 封装的MVC版后台管理系统
项目名称:学生信息管理系统1.0 后台框架:.Net Core 3.1 + EF Core yrjw.ORM.Chimp 前端框架:ASP.NET Core MVC + LayUI + Bo ...
- quartz定时定时任务执行两次
quartz框架没问题. 流程: sping-quartz配置 <?xml version="1.0" encoding="UTF-8"?> < ...
- 分享基于EF+MVC+Bootstrap的通用后台管理系统及架构
基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通用配置及服务调用, 提供了OA.CRM.CMS的原型实例,适合快速构建中小型互联网及行业 ...
- RDIFramework.NET-.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(MVC版)
RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(MVC版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之产品管理 ...
- 用最基本的EF+MVC+JQ+AJAX+bootstrap实现权限管理的简单实例 之登陆和操作权限
先来一堆关于上篇文章的废话(不喜者点此隐藏) 今天把博客加了个小功能,就是点标题可以隐藏或展示相关内容,做法很傻,就是引用了bootstrap的两个css类和全部的js文件,其实这样的小功能完全应该自 ...
- 分享基于EF+MVC+Bootstrap的通用后台管理系统及架构(转)
http://www.cnblogs.com/guozili/p/3496265.html 基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通 ...
- 使用Quartz创建定时任务
项目开发中经常需要定时循环执行某些任务 比如定时发送报表,定时发送邮件,亦或者定时清理缓存,定时更新数据等等 有些时候可以简单地利用Windows Server的计划任务执行程序 Linux也有相应的 ...
随机推荐
- Android(java)同步方法synchronized
synchronized 是java语言keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. synchronized keyword,它包含两 ...
- Mybaits 使用多数据库源错误 --MapperScannerConfigurer配置
我在配置文件里面配置了一个数据源,数据源参数是根据配置文件加载.数据源在mybaits和自定义数据工具类中使用,但是启动工程后,报错如下: ### Cause: org.springframewor ...
- mysql之limit m,n
limit是mysql的语法 select * from table limit [m],n; 其中,m—— [m]为可选,如果填写表示skip步长,即跳过m条. n——显示条数.指从第m+1条记录开 ...
- 大道至简的C语言内存管理
C语言内存的开辟和释放需要程序员自己来实现. 而C语言的内存开辟和释放只在stdlib.h里面提供了四个函数,这么简洁的设计就足以完成一切工作. C++里面各种类型的指针漫天飞舞,显得啰嗦冗余. ca ...
- Android开发环境——连接驱动ADB相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- linux shell 脚本攻略学习16--wc命令详解,tree命令详解
在文本处理的工作中,统计文件的行数,单词数和字符数非常有用.而对于开发人员本身来说,统计LOC(line of code ,代码行数)是一件重要的工作.linux中有什么命令可以帮助我们做统计呢?没错 ...
- 关于解锁美版Play市场
关于解锁美版Play市场(本帖已经突破了G+的500评论上限,如有问题请转载留言) 我对这个问题思考的很深刻也思考了很久,作为一个深度google脑残粉怎么能用不完整的Play Store呢?那人生岂 ...
- centos 6&7 升级openssh
1.查看现在的版本 # rpm -qa | grep openssh openssh-clients-6.6.1p1-22.el7.x86_64 openssh-server-6.6.1p1-22.e ...
- Html5 canvas 绘制彩票走势图
因须要 要实现一个类似彩票走势图的功能,初次学Html5 ,非常多地方不明白,前段时间也发帖请教过这个问题.也是没给个明白说话,在网上搜了非常多,也没有实现的样例,今天细致研究了下.发现事实上也不是非 ...
- CTreeCtrl鼠标双击响应函数中怎么知道双击的是哪个子项?
原帖链接: http://bbs.csdn.net/topics/310185501 楼主: CTreeCtrl鼠标双击响应函数中怎么知道双击的是哪个子项? 6楼: CPoint pt;GetCurs ...