亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

ESBasic 可復(fù)用的.NET類庫(08) -- 定時(shí)任務(wù)

系統(tǒng) 1852 0

1. 緣起:

假設(shè)我們的報(bào)表系統(tǒng)需要在每天的 00:05:00 統(tǒng)計(jì)前一天的報(bào)表數(shù)據(jù),需要在每周一的 00:30:00 統(tǒng)計(jì)上周的報(bào)表數(shù)據(jù),又需要在每月 1 日的 00:30:00 統(tǒng)計(jì)上月的報(bào)表數(shù)據(jù)。

這些報(bào)表統(tǒng)計(jì)任務(wù)是很常見的系統(tǒng)需求,對于類似這樣的在指定時(shí)刻執(zhí)行的定時(shí)任務(wù),我使用 ESBasic.Threading.Timers.TimingTaskManager (定時(shí)任務(wù)管理器)來處理它。

TimingTaskManager 與前面講的回調(diào)定時(shí)器 CallbackTimer 的區(qū)別在于, CallbackTimer 是參考當(dāng)前時(shí)間再延遲一段時(shí)間后執(zhí)行,而 TimingTaskManager 管理的任務(wù)是要求在指定的具體時(shí)間點(diǎn)執(zhí)行。

定時(shí)任務(wù)管理器的形象示意圖如下:

ESBasic 可復(fù)用的.NET類庫(08) -- 定時(shí)任務(wù)管理器 TimingTaskManager

2.
適用場合:

如果你的任務(wù)滿足以下條件,則可以使用 TimingTaskManager 來解決任務(wù)的定時(shí)執(zhí)行:

(1) 任務(wù)需要在每小時(shí)、每天、每周、或每月的某個(gè)固定的時(shí)間點(diǎn)執(zhí)行。

(2) 可以允許任務(wù)執(zhí)行的時(shí)間點(diǎn)與期望的時(shí)刻存在一定的誤差。

3 .設(shè)計(jì)思想與實(shí)現(xiàn)

在介紹 TimingTaskManager 之前,我們要先介紹 TimingTask 這個(gè)類,它表示一個(gè)定時(shí)任務(wù),正是它封裝了任務(wù)的執(zhí)行頻率、執(zhí)行的具體時(shí)間和要執(zhí)行的目標(biāo)方法。 TimingTask 的類圖如下:
ESBasic 可復(fù)用的.NET類庫(08) -- 定時(shí)任務(wù)管理器 TimingTaskManager
我們看到,
ExcuteTime 屬性是一個(gè) ShortTime 類型,指定要執(zhí)行任務(wù)的具體時(shí)刻。而 TimingTaskType 屬性決定了 TimingTask 執(zhí)行的頻率, TimingTaskType 定義如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> [ EnumDescription( " 定時(shí)任務(wù)的類型 " )]
public enum TimingTaskType
{
[
EnumDescription( " 每小時(shí)一次 " )]
PerHour,
[
EnumDescription( " 每天一次 " )]
PerDay,
[
EnumDescription( " 每周一次 " )]
PerWeek,
[
EnumDescription( " 每月一次 " )]
PerMonth
}

要注意的是,如果 TimingTaskType 屬性的值為 PerHour ,則將忽略 ExcuteTime Hour 屬性。

同樣的, DayOfWeek 屬性只有在 TimingTaskType 屬性的值為 PerWeek 時(shí)才有效,表示在周幾執(zhí)行。 Day 屬性只有在 TimingTaskType 屬性的值為 PerMonth 時(shí)才有效,表示在每月的幾號(hào)執(zhí)行。

TimingTask 的實(shí)現(xiàn)中, IsOnTime 方法的實(shí)現(xiàn)特別要引起注意。因?yàn)槲覀兊亩〞r(shí)任務(wù)管理器是基于定時(shí)器 Timer 工作的,而定時(shí)器的掃描時(shí)間是有間隔的,所以,在某個(gè) ExcuteTime 所代表的真正的執(zhí)行時(shí)間點(diǎn)的左右的兩個(gè)掃描時(shí)刻,可能都會(huì)被認(rèn)為是符合執(zhí)行條件的(比如,兩個(gè)掃描時(shí)刻距離真正執(zhí)行時(shí)刻的距離都在 1 秒之內(nèi)),如果是這樣,目標(biāo)任務(wù)將會(huì)被執(zhí)行兩次――這是我們不希望發(fā)生的。為了避免這種情況的出現(xiàn),我們在 TimingTask 中使用 lastRightTime 成員來記錄上次執(zhí)行的時(shí)間,如果 lastRightTime 與當(dāng)前時(shí)間的差值 2 倍的掃描間隔以內(nèi),則將認(rèn)為當(dāng)前時(shí)間不符合條件。正如下面代碼所示:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> #region 防止在臨界點(diǎn)時(shí),執(zhí)行兩次
TimeSpan span = now - this .lastRightTime;
if (span.TotalMilliseconds < checkSpanSeconds * 1000 * 2 )
{
return false ;
}
#endregion


接下來,我們將注意力轉(zhuǎn)移到 TimingTaskManager 上來。有了 TimingTask 的封裝, TimingTaskManager 所要做的事情就非常簡單,其要點(diǎn)歸結(jié)如下:

(1) TimingTaskManager 使用 Timer 來進(jìn)行定時(shí)掃描,以判斷每個(gè)任務(wù)是否到了要執(zhí)行的時(shí)間點(diǎn)。 TimerSpanInSecs 屬性指定了掃描的時(shí)間間隔。

(2) 當(dāng)某個(gè)任務(wù)的執(zhí)行時(shí)刻到來, TimingTaskManager 會(huì)異步執(zhí)行該任務(wù),這樣不會(huì)阻塞當(dāng)前的 foreach 遍歷。

(3) TimingTaskManager 提供了 RegisterTask UnRegisterTask 方法,用于在運(yùn)行的過程中可以動(dòng)態(tài)的增加或移除任務(wù)。

(4) TimingTaskManager 必須對任務(wù)列表 taskList 進(jìn)行加鎖,以確保集合的線程安全。因?yàn)槎〞r(shí)器本身就是在另外一個(gè)線程上執(zhí)行 Worker 方法的,如果在執(zhí)行 Worker 方法的同時(shí),有其它線程調(diào)用 RegisterTask UnRegisterTask 方法,就會(huì)導(dǎo)致 Worker 方法中的 foreach 遍歷動(dòng)作拋出異常。

4. 使用時(shí)的注意事項(xiàng)

(1) 由于 TimingTaskManager 采用 Timer 進(jìn)行定時(shí)掃描,所以,任務(wù)執(zhí)行的時(shí)間點(diǎn)與期望的時(shí)間點(diǎn)的最大誤差就是 TimerSpanInSecs 的值。由于 TimerSpanInSecs 能取的最小值為 1 秒,所以 TimingTaskManager 能夠達(dá)到的最小誤差為 1 秒。如果你的任務(wù)期望被更精確的執(zhí)行,那么 TimingTaskManager 就不適合你。

(2) TimingTaskType 指定的頻率只能是:每小時(shí)一次、每天一次、每周一次、每月一次。但是對于一個(gè)類似你希望在每周二、四中午 12:00:00 執(zhí)行的任務(wù),我們可以采用變通的做法,那就是將其視為兩個(gè)任務(wù):一個(gè)在每周二的中午 12:00:00 執(zhí)行,另一個(gè)在每周四的中午 12:00:00 執(zhí)行。如此,我們可以使用 TimingTaskManager 提供的最基礎(chǔ)的定時(shí)頻率經(jīng)過組合來處理更高級、更復(fù)雜的定時(shí)任務(wù)。

(3) 由于 ITimingTaskExcuter ExcuteOnTime 方法是在后臺(tái)線程池中的某個(gè)線程上執(zhí)行的,所以其拋出的任何異常都會(huì)被忽略。最好的辦法是,在實(shí)現(xiàn) ExcuteOnTime 方法是確保在其內(nèi)部 catch 住了所有的異常。

5. 擴(kuò)展

定時(shí)任務(wù)管理器 TimingTaskManager 暫時(shí)沒有任何擴(kuò)展。

注:ESBasic源碼可到 http://esbasic.codeplex.com/ 下載。
ESBasic討論:37677395
ESBasic開源前言


ESBasic 可復(fù)用的.NET類庫(08) -- 定時(shí)任務(wù)管理器 TimingTaskManager


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦?。?!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色中文字幕 | 久久精品国产6699国产精 | 九九视频在线播放 | 久久综合九九亚洲一区 | 国产91在线|亚洲 | 国产精品视频色拍拍 | 一二三四社区在线播放 | 四虎永久免费网站免费观看 | 911精品国产91久久久久 | 中文字幕在线二区 | 欧美日本视频在线观看 | 久久久久久久网 | 最新久久精品 | 国产精品久久综合桃花网 | 国产精品香蕉一区二区三区 | 亚洲天码中字 | 91精品国产高清91久久久久久 | 成人黄色一级毛片 | 欧美成人性视频在线黑白配 | 欧美成人性做爰网站免费 | 天天干天天射天天 | 天天色网站| 国产一区中文字幕在线观看 | 日本免费新一区二区三区 | 国产免费不卡v片在线观看 国产免费不卡视频 | 亚洲精品一区二区三区香蕉在线看 | 国产精品久久成人影院 | 四虎永久免费观看 | 免费一级毛片不卡在线播放 | 久久国产精品免费视频 | 免费视频成人国产精品网站 | 手机看片日韩日韩 | 99九九成人免费视频精品 | 亚欧美 | 久久综合久久综合久久 | 欧美真人视频一级毛片 | 日韩字幕在线 | 亚洲精品久久麻豆蜜桃 | 成人精品视频在线观看播放 | 久久日精品 | 欧美 日产 国产精选 |