1.缘起:
假设我们的报表系统需要在每天的00:05:00统计前一天的报表数据,需要在每周一的00:30:00统计上周的报表数据,又需要在每月1日的00:30:00统计上月的报表数据。
这些报表统计任务是很常见的系统需求,对于类似这样的在指定时刻执行的定时任务,我使用ESBasic.Threading.Timers.TimingTaskManager(定时任务管理器)来处理它。
TimingTaskManager与前面讲的回调定时器CallbackTimer的区别在于,CallbackTimer是参考当前时间再延迟一段时间后执行,而TimingTaskManager管理的任务是要求在指定的具体时间点执行。
定时任务管理器的形象示意图如下:
2.适用场合:
如果你的任务满足以下条件,则可以使用TimingTaskManager来解决任务的定时执行:
(1)任务需要在每小时、每天、每周、或每月的某个固定的时间点执行。
(2)可以允许任务执行的时间点与期望的时刻存在一定的误差。
3.设计思想与实现
在介绍TimingTaskManager之前,我们要先介绍TimingTask这个类,它表示一个定时任务,正是它封装了任务的执行频率、执行的具体时间和要执行的目标方法。TimingTask的类图如下:
我们看到,ExcuteTime属性是一个ShortTime类型,指定要执行任务的具体时刻。而TimingTaskType属性决定了TimingTask执行的频率,TimingTaskType定义如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> [EnumDescription("定时任务的类型")]
publicenumTimingTaskType
{
[EnumDescription("每小时一次")]
PerHour,
[EnumDescription("每天一次")]
PerDay,
[EnumDescription("每周一次")]
PerWeek,
[EnumDescription("每月一次")]
PerMonth
}
要注意的是,如果TimingTaskType属性的值为PerHour,则将忽略ExcuteTime的Hour属性。
同样的,DayOfWeek属性只有在TimingTaskType属性的值为PerWeek时才有效,表示在周几执行。Day属性只有在TimingTaskType属性的值为PerMonth时才有效,表示在每月的几号执行。
在TimingTask的实现中,IsOnTime方法的实现特别要引起注意。因为我们的定时任务管理器是基于定时器Timer工作的,而定时器的扫描时间是有间隔的,所以,在某个ExcuteTime所代表的真正的执行时间点的左右的两个扫描时刻,可能都会被认为是符合执行条件的(比如,两个扫描时刻距离真正执行时刻的距离都在1秒之内),如果是这样,目标任务将会被执行两次――这是我们不希望发生的。为了避免这种情况的出现,我们在TimingTask中使用lastRightTime成员来记录上次执行的时间,如果lastRightTime与当前时间的差值2倍的扫描间隔以内,则将认为当前时间不符合条件。正如下面代码所示:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> #region防止在临界点时,执行两次
TimeSpanspan=now-this.lastRightTime;
if(span.TotalMilliseconds<checkSpanSeconds*1000*2)
{
returnfalse;
}
#endregion
接下来,我们将注意力转移到TimingTaskManager上来。有了TimingTask的封装,TimingTaskManager所要做的事情就非常简单,其要点归结如下:
(1)TimingTaskManager使用Timer来进行定时扫描,以判断每个任务是否到了要执行的时间点。TimerSpanInSecs属性指定了扫描的时间间隔。
(2)当某个任务的执行时刻到来,TimingTaskManager会异步执行该任务,这样不会阻塞当前的foreach遍历。
(3)TimingTaskManager提供了RegisterTask和UnRegisterTask方法,用于在运行的过程中可以动态的增加或移除任务。
(4)TimingTaskManager必须对任务列表taskList进行加锁,以确保集合的线程安全。因为定时器本身就是在另外一个线程上执行Worker方法的,如果在执行Worker方法的同时,有其它线程调用RegisterTask和UnRegisterTask方法,就会导致Worker方法中的foreach遍历动作抛出异常。
4. 使用时的注意事项
(1)由于TimingTaskManager采用Timer进行定时扫描,所以,任务执行的时间点与期望的时间点的最大误差就是TimerSpanInSecs的值。由于TimerSpanInSecs能取的最小值为1秒,所以TimingTaskManager能够达到的最小误差为1秒。如果你的任务期望被更精确的执行,那么TimingTaskManager就不适合你。
(2)TimingTaskType指定的频率只能是:每小时一次、每天一次、每周一次、每月一次。但是对于一个类似你希望在每周二、四中午12:00:00执行的任务,我们可以采用变通的做法,那就是将其视为两个任务:一个在每周二的中午12:00:00执行,另一个在每周四的中午12:00:00执行。如此,我们可以使用TimingTaskManager提供的最基础的定时频率经过组合来处理更高级、更复杂的定时任务。
(3)由于ITimingTaskExcuter的ExcuteOnTime方法是在后台线程池中的某个线程上执行的,所以其抛出的任何异常都会被忽略。最好的办法是,在实现ExcuteOnTime方法是确保在其内部catch住了所有的异常。
5.扩展
定时任务管理器TimingTaskManager暂时没有任何扩展。
注:ESBasic源码可到http://esbasic.codeplex.com/下载。
ESBasic讨论:37677395
ESBasic开源前言
分享到:
相关推荐
本人将 zhuweisky博主的博客整理成了PDF文件,以便于脱机浏览,没有经过博主的同意就这么做 实在是不好意思^-^ 现将其资料免费下载 以示对博主的尊重 源博客地址:...
LiteGo:「迷你」的Android异步并发类库LiteGo是一款基于Java语言的「异步并发类库」,它的核心是一枚「迷你」并发器,它可以自由地设置同一时段的最大「并发」数量,等待「排队」线程数量,还可以设置「排队策略」...
.NET设计规范:约定、惯用法与模式,在.net环境下进行开发设计的经典之作,权威指导.
新版根据.NET Framework 3.0和3.5的新特性做了全面更新,主要关注的是直接影响框架可编程能力的设计问题。遵守这些规范对于使用.NET Framework创建高质量的应用程序至关重要。 本书提供配套光盘,内含Designing ...
NET应用架构设计原则、模式与实践.pdf NET应用架构设计原则、模式与实践.pdf
灵活易用的工作流组件、数据字典管理组件、在线表单设计组件、丰富的报表统计组件、即时通讯(IM)组件、邮件中心组件、微信开发相关组件、任务调度组件、自动升级组件、多语言模块,各种常用的商业控件,强大的代码...
新版根据.NET Framework 3.0和3.5的新特性做了全面更新,主要关注的是直接影响框架可编程能力的设计问题。遵守这些规范对于使用.NET Framework创建高质量的应用程序至关重要。 本书提供配套光盘,内含Designing ...
自己写的ado.net类库,已实现有关数据库操作的各种方法,子类只需提供数据库连接,即可调用,极大了实现了代码复用.这是我针对实际开发中经常需要重复开发数据库操作而提出的解决方案. 注意,该类实现的是关于sqlserver...
5.7.4 参数数量可变的成员 147 5.7.5 指针参数 150 5.8 小结 152 第6章 为扩展性而设计 153 6.1 扩展机制 153 6.1.1 非密封类 153 6.1.2 保护成员 155 6.1.3 事件与回调函数 156 6.1.4 虚成员 ...
博文地址:http://blog.csdn.net/csnd_ayo/article/details/72457190
这里收集一些著名的 C/C++ 开发库、SDK、类库、可复用类与结构代码 等信息,列举它们的介绍、参考和网站链接,为各位 C/C++ 程序员和爱好者提供检索和查阅类库的方便。 下面收集的 C/C++ 类库介绍整理来源于文章:...
模块连接到多路复用总线前,主机应断电并设置好模块上的地址拨码开,非常详细。海康DS-19A08-BN连接图
自从.NET推出以来,他已使用.NET帮助很多行业的用户开发了体现其商业理念的软件产品.Xin Chen是.NET和EAI方面的专家,他与Microsoft和Accenture等多家技术领先的公司合作,为它们的客户提供了优秀的解决方案....
有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年JAVA架构设计经验,擅长JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年...
此外,还可以创建一个新类库实现软件复用。 • 第十章介绍.NET下的数据库支持,阐述了ADO.NET的基本概念和结构,并通过示例詊细介绍C#下Web Service数据库访问的方法。 • 第十一章将在以前的基础上介绍一个...
这些规范历经.NET框架三个版本的长期开发,凝聚了数千名开发人员的经验和智慧。微软的各开发组正在使用这些规范开发下一代影响世界的软件产品。 第1章 概述 1 1.1 精心设计的框架所具备的品质 2 1.1.1 精心...
Coalesys PanelBar + R.a.d Treeview +Xml 构建的Asp.net 菜单和权限管理模块 突破屏蔽限制,自己的网站使劲弹新IE窗口 对页面SCROLLING的CSS不能生效原因 .Net 中IE使用WinForm控件的使用心得。 动态加载用户控件的...
有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年JAVA架构设计经验,擅长JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年...
有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年JAVA架构设计经验,擅长JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年...