简易任务调度实现--可用于windows服务/asp.net网站执行后台计算

news/2024/5/10 2:55:24/文章来源:https://blog.csdn.net/weixin_30507269/article/details/99789572

在项目开发中经常会遇到后台定时任务调度执行计算的需求,为此我实现了一个简易的任务调度框架。

首先,我只实现的简易调度框架,原则上在同一时间点只执行一个任务,实现在每天指定的时间段内执行一次或固定频率(只是相对固定)执行多次任务。

其次,这个简易框架可用于windows 服务或asp.net网站实现后台定时调度任务计算。

要实现任务调度,使用核心技术的就是System.Timers.Timer对象。

下面代码实现:

1.定义内部使用的任务类Task;

View Code
 1 private class Task
2 {
3 public TimeSpan Start; //每天任务开始的时间点,从00:00开始算起
4 public TimeSpan End; //每天任务结束的时间点,从00:00开始算起
5 public bool Once = false; //指定任务是否每天只执行一次
6 public DateTime Executed = DateTime.MinValue; //任务在最后一次执行的时间点
7 public TimeSpan Interval; //任务执行频率
8 public Action action; //匿名委托,用于任务计算
9 public override string ToString()
10 {
11 return string.Format(@"Task({0}) Start:{1},End:{2},Once:{3},Interval:{4},Action:{5},Executed:{6}", this.GetHashCode(), this.Start, this.End, this.Once, this.Interval, this.action, this.Executed);
12 }
13 }

2.任务调试类的主要接口(核心功能)

View Code
class Schedule : IDisposable
{
private class Task
{
public TimeSpan Start; //每天任务开始的时间点,从00:00开始算起
public TimeSpan End; //每天任务结束的时间点,从00:00开始算起
public bool Once = false; //指定任务是否每天只执行一次
public DateTime Executed = DateTime.MinValue; //任务在最后一次执行的时间点
public TimeSpan Interval; //任务执行频率
public Action action; //匿名委托,用于任务计算
public override string ToString()
{
return string.Format(@"Task({0}) Start:{1},End:{2},Once:{3},Interval:{4},Action:{5},Executed:{6}", this.GetHashCode(), this.Start, this.End, this.Once, this.Interval, this.action, this.Executed);
}
}

/// <summary>
/// 在每天指定的时间段内以相对固定的频率执行任务
/// </summary>
/// <param name="start">任务开始时间点,从00:00开始算起</param>
/// <param name="end">任务结束时间点,从00:00开始算起</param>
/// <param name="interval">任务调试效率</param>
/// <param name="action">匿名委托,用于任务计算</param>
public void Execute(TimeSpan start, TimeSpan end, TimeSpan interval, Action action)
{
AddTask(new Task()
{
action = action,
End = end,
Interval = interval,
Once = false,
Start = start
});
}

/// <summary>
/// 在每天指定的时间段内执行一次任务
/// </summary>
/// <param name="start">任务开始时间点,从00:00开始算起</param>
/// <param name="end">任务结束时间点,从00:00开始算起</param>
/// <param name="action">匿名委托,用于任务计算</param>
public void ExecuteOnce(TimeSpan start, TimeSpan end, Action action)
{
AddTask(new Task()
{
action = action,
End = end,
Once = true,
Start = start
});
}

/// <summary>
/// 开始调度任务
/// </summary>
public void Start()
{
this.onGoing = true;
this.timer.Enabled = true;
}

/// <summary>
/// 结束高度任务
/// </summary>
public void Stop()
{
this.onGoing = false;
this.timer.Enabled = false;
}



private System.Timers.Timer timer;//timer对象,用于定时检时任务执行点
private volatile bool onGoing = false; //指示任务调度是否持续运行
private List<Task> tasks = new List<Task>(); //任务列表,用于任务排序

/// <summary>
/// 构造函数,默认以5秒的频率检查任务执行时间点
/// </summary>
public Schedule()
: this(5000)
{

}

/// <summary>
/// 构造函数,默认以指定的频率检查任务执行时间点
/// </summary>
/// <param name="interval"></param>
public Schedule(double interval)
{
timer = new System.Timers.Timer(interval);
timer.AutoReset = false; //这是整个框架实现的关键所在,后面会进一步说明
timer.Enabled = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); //用于检查任务时间点的匿名委托
}

/// <summary>
/// 添加一个任务到任务列表
/// </summary>
/// <param name="task"></param>
private void AddTask(Task task)
{
if (task.Once == true)
tasks.Insert(0, task); //每天一次的任务优先
else
tasks.Add(task);
}


/// <summary>
/// 用于检查任务时间点的匿名委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (this.onGoing == true) //判断调度是否继续
{
if (tasks.Count > 0)
{
int index = 0;
while (true)
{
Task task = tasks[index++]; //获取任务列表中的第一个任务

if (this.onGoing == false) break; //判断调度是否继续

if (CompareTime(task)) //比较任务时间点
{
ExecuteTask(task); //执行任务,同时更新任务最后执行时间点
SortTasks(); //对任务列表进行排序,确定下一次最先执行的任务
break;
}
}
}
}

if (this.onGoing == true)//判断调度是否继续
{
this.timer.Enabled = true; //激活timer,在指定时间再进一次任务时间点检查
}
}

/// <summary>
/// 任务列表排序,将一次性的任务排在前面,将最近已执行的任务放在最后
/// </summary>
private void SortTasks()
{
if (tasks.Count <= 1) return;
tasks.Sort(new Comparison<Task>(delegate(Task Task0, Task Task1)
{
if (Task0.Once == true && Task1.Once == false)
{
return -1;
}

if (Task0.Once = true && Task1.Once == true)
{
return Task0.Executed < Task1.Executed ? -1 : 1;
}

if (Task0.Once == false && Task1.Once == true)
{
return 1;
}

return Task0.Executed < Task1.Executed ? -1 : 1;
}));

}

/// <summary>
/// 比较任务时间点
/// </summary>
/// <param name="task">任务</param>
/// <returns></returns>
private bool CompareTime(Task task)
{

DateTime Now = DateTime.Now; //当前时间点

//计算任务在当天内开始执行时间
DateTime startTime = new DateTime(Now.Year, Now.Month, Now.Day, task.Start.Hours, task.Start.Minutes, task.Start.Seconds);
//计算任务在当天内结束执行时间
DateTime endTime = new DateTime(Now.Year, Now.Month, Now.Day, task.End.Hours, task.End.Minutes, task.End.Seconds);
//任务跨天执行,调整时间点
if (startTime > endTime) endTime += new TimeSpan(24, 0, 0);

//如果是每天一次的任务,而且已经执行过一次
if (task.Once == true && startTime <= task.Executed && task.Executed <= endTime)
{
return false;
}

return startTime <= Now && Now <= endTime; //如果当前时间点,在任务执行时间段内,则返真
}

/// <summary>
/// 执行任务
/// </summary>
/// <param name="task"></param>
private void ExecuteTask(Task task)
{
if (task.action != null)
{
//如果当前时间在任务执行频率内,则执行
if (task.Executed == DateTime.MinValue || DateTime.Now - task.Executed >= task.Interval)
{
task.action();
task.Executed = DateTime.Now; //更新任务最后执行时间
}
}
}


#region IDisposable Members

public void Dispose()
{
this.timer.Dispose();
}

#endregion
}

3.在asp.net网站中调度任务

View Code
public class Global : System.Web.HttpApplication
{

Schedule schedule = new Schedule(10000);
/// <summary>
/// IIS启动时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_Start(object sender, EventArgs e)
{
//每天从11:30至17:30,每隔一分钟执行一次任务
schedule.Execute(new TimeSpan(11, 30, 0), new TimeSpan(17, 30, 0), new TimeSpan(0,1,0), delegate()
{
AutoQuery.Execute();
});

//每天从11:00至11:20,只执行一次任务
schedule.ExecuteOnce(new TimeSpan(11, 0, 0), new TimeSpan(11, 20, 0), delegate()
{
AutoQuery.PrepareTasks();
});

//开始任务调度
schedule.Start();
}

protected void Application_End(object sender, EventArgs e)
{
//停止调度任务
schedule.Stop();
}

protected void Session_Start(object sender, EventArgs e)
{

}

protected void Application_BeginRequest(object sender, EventArgs e)
{

}

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{

}

protected void Application_Error(object sender, EventArgs e)
{

}

protected void Session_End(object sender, EventArgs e)
{

}


}

这此代码已经在项目中使用,已经通过本人多次测试。

完.




转载于:https://www.cnblogs.com/flysun/archive/2012/01/09/2317570.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_747321.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站快照被劫持怎么解决?

网站安全服务 网站安全是重中之重对此我们Sinesafe对于网站被挂马被黑的防范意识,如何判断网站被黑,网站被挂马,网站快照被劫持,网站快照被篡改,导致被百度网址安全中心提醒您&#xff1a;该页面可能存在违法信息。 网站服务是否稳定&#xff0c;对用户、站方和搜索引擎来说都非…

网站开发最好用的画折线图、饼状图、柱状图方法

一、FusionChartsFree 是我用过最方便&#xff0c;最有效的网页开发中画统计图方案。完全免费而且开源。因基于FLASH&#xff0c;所以支持ASP/JS/ASP.NET/PHP/JSP...等等等等。下载地址&#xff1a;http://www.fusioncharts.com/free/download/ 【只需要简单注册一下就可以down…

30多个国外电子商务网站欣赏

30多个设计精良的电子商务网站。国外知名的开源网店程序有Magento、OSCommerce、Zen-cart、opencart等&#xff0c;国内的 有Ecshop和ShopEX等&#xff0c;在遵守相关的授权协议的情况下&#xff0c;你可以免费的使用这些程序搭建一个网店。一个设计精良的电子商务网站显然将给…

Piwik 1.9 发布,网站访问统计系统

Piwik 1.9 发布了&#xff0c;该版本包含三个主要功能&#xff1a;网页过渡、网站搜索分析和更简单的地理位置配置&#xff0c;详情请看 Piwik 1.9 release blog post 同时发布的还有 Piwik Mobile 1.9 Piwik是一套基于PhpMySQL技术构建的开源网站访问统计系统&#xff0c;前身…

服务器里如何查杀网站后门文件

收到阿里云的短信提醒说是网站存在后门&#xff0c;webshell恶意通信行为&#xff0c;紧急的安全情况&#xff0c;我第一时间登录阿里云查看详情&#xff0c;点开云盾动态感知&#xff0c;查看了网站木马的详细路径以及webshell的特征&#xff0c;网站从来没有出现过这种情况&a…

社交系统ThinkSNS+在研发过程中,如何做到 Laravel 配置可以网站后台配置

什么是ThinkSNS ThinkSNS(简称TS)&#xff0c;一款全平台综合性社交系统&#xff0c;为国内外大中小企业和创业者提供社会化软件研发及技术解决方案。 本文分享下利用 Laravel 的 Bootstrapping 达到网站后台设置 laravel 配置。 需求场景 首先&#xff0c;ThinkSNS 作为一个用…

大型网站技术架构(八)网站的安全架构

2019独角兽企业重金招聘Python工程师标准>>> 从互联网诞生起&#xff0c;安全威胁就一直伴随着网站的发展&#xff0c;各种Web攻击和信息泄露也从未停止。常见的攻击手段有XSS攻击、SQL注入、CSRF、Session劫持等。 1、XSS攻击 XSS攻击即跨站点脚本攻击&#xff08;…

创业团队如何保护自己的网站安全?

今天在知乎上有人邀请我回答一个问题&#xff1a;创业团队如何在低成本的情况下保护自己的网站安全&#xff1f; 简略答一下。 一般来说&#xff0c;很多安全专家都会告诉你没有绝对的安全&#xff0c;如果黑客一定要长期盯着你的公司有针对性的渗透&#xff0c;很少有可以幸免…

55个漂亮的蓝色风格网站设计作品欣赏(下篇)

蓝色非常纯净&#xff0c;通常让人联想到海洋、天空、水、宇宙。纯净的蓝色表现出一种美丽、冷静、理智、安详与广阔。今天&#xff0c;本文收集了30个漂亮的蓝色风格的网站设计作品与大家分享&#xff0c;一起欣赏。 icebrrg powerset Birdie designchuchi.ch StrawPoll lucin…

【转】https,https的本地测试环境搭建,asp.net结合https的代码实现,http网站转换成https网站之后遇到的问题...

正需要这个&#xff0c;写的很好&#xff0c;就转过来了 转自&#xff1a; http://www.cnblogs.com/naniannayue/ 一&#xff1a;什么是https SSL&#xff08;Security Socket Layer&#xff09;全称是加密套接字协议层&#xff0c;它位于HTTP协议层和TCP协议层之间&#x…

如何让你的网站支持 IE9 Pinned Site (Part 2 - 实战)

该如何展示 IE9 Pinned Site 呢&#xff1f;我可以写一个新的应用&#xff0c;完全是为了展示 Pinned Site 的特性&#xff0c;但这样就像是为了实现这些特性而利用这些特性。所以我想还是升级一个现有的网站好了&#xff0c;这样更能说明 Pinned Site 是如何起到优化用户体验的…

Jsoup开发网站客户端第二篇,图片轮播,ScrollView兼容ListView

最近一段日子忙的焦头烂额&#xff0c;代码重构&#xff0c;新项目编码&#xff0c;导致jsoup开发网站客户端也没时间继续下去&#xff0c;只能利用晚上时间去研究了。今天实现美食网首页图片轮播效果&#xff0c;网站效果图跟Android客户端实现如图&#xff1a; 从浏览器开发者…

大型网站技术架构(五)网站高可用架构

2019独角兽企业重金招聘Python工程师标准>>> 网站的可用性&#xff08;Avaliability&#xff09;描述网站可有效访问的特性。 1、网站可用性的度量与考核 网站不可用时间&#xff08;故障时间&#xff09;故障修复时间点-故障发现&#xff08;报告&#xff09;时间点…

大型网站技术架构(八)网站的安全架构

2019独角兽企业重金招聘Python工程师标准>>> 从互联网诞生起&#xff0c;安全威胁就一直伴随着网站的发展&#xff0c;各种Web攻击和信息泄露也从未停止。常见的攻击手段有XSS攻击、SQL注入、CSRF、Session劫持等。 1、XSS攻击 XSS攻击即跨站点脚本攻击&#xff08;…

爬取简单反爬虫网站实战

实战一&#xff0c;爬取京东商品 import requestsurl "https://item.jd.com/27217068296.html"try:r requests.get(url)r.raise_for_status() #获取爬取失败异常r.encoding r.apparent_encodingprint(r.text[:1000]) except:print("爬取失败")结果&a…

深入浅出SharePoint——使用HTTPS来访问网站

如下图所示&#xff1a;由于默认的SSL端口443已经被其他web application占用了&#xff0c;所以我们指定4433为https的端口。这样我们在配置mapping关系的时候就要使用底油端口为4433的网址。 转载于:https://www.cnblogs.com/mingle/archive/2013/05/30/3107731.html

职业社交网站为何比微博更有价值

“微时代”的风生水起&#xff0c;让越来越多的企业一头热地投入到微博营销中去&#xff0c;这当然与微博庞大的用户群息息相关。目前&#xff0c;新浪微博的用户已经突破了2亿。这样看&#xff0c;微博目前似乎是线上领域无敌手&#xff0c;在我看来却未必如此&#xff0c;比如…

做网站用UTF-8编码还是GB2312编码?

经常我们打开外国网站的时候出现乱码&#xff0c;又或者打开很多非英语的外国网站的时候&#xff0c;显示的都是口口口口口的字符&#xff0c; WordPress程序是用的UTF-8&#xff0c;很多cms用的是GB2312。 ● 为什么有这么多编码&#xff1f; ● UTF-8和GB2312有什么区别&…

全面解读中英文网站中字体的异同

英文网站与中文网站的异同不仅仅是使用中文与英文的差别。由于中文字形复杂&#xff0c;并且电脑上的中文字体设计相对落后&#xff0c;这使得设计中文网页要比英文网页更困难。不顾及中文字体的特殊性&#xff0c;简单的照搬英文网页的设计方法&#xff0c;经常会降低中文网页…

网站建设-数据库横向扩展

数据库横向扩展 在网站建设的过程中&#xff0c;一个高扩展性的架构设计可以保证当网站业务量和访问量达到零界点时我们能够以较低的成本对现有系统进行扩展。而网站系统最难扩展的部分通常是数据库或者持久化存储。当今最流行的RDBMS数据库&#xff0c;如Oracle&#xff0c;Sq…