最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#實(shí)現(xiàn)自定義定時(shí)組件的方法

 更新時(shí)間:2014年08月15日 10:48:33   投稿:shichen2014  
這篇文章主要介紹了C#實(shí)現(xiàn)自定義定時(shí)組件的方法,很實(shí)用的功能,需要的朋友可以參考下

本文實(shí)例展示的是一個(gè)自定義的定時(shí)器組件,有別于.NET Framework里面提供的幾個(gè)Timer。首先說說該組件開發(fā)背景,發(fā)現(xiàn)現(xiàn)在手頭上的工作離不開定時(shí),定時(shí)做一個(gè)任務(wù),什么都是定時(shí)去做什么什么,隔某段時(shí)間干某件事情,都離不開“定時(shí)”這個(gè)詞。眾所周知這個(gè)要用到多線程,在多篇關(guān)于多線程的文章里面有提過做一些周期性的操作時(shí)最好用Timer,當(dāng)然這個(gè)Timer肯定是Threading.Timer,并不是WinForm控件里面的Timer。但我覺得在我的應(yīng)用中Timer不夠滿足需求。

1.Timer只能在做任務(wù)與任務(wù)之間相隔一段時(shí)間的操作,如下圖

但我需要的是這次任務(wù)開始的時(shí)刻到下次任務(wù)開始時(shí)刻是相隔同等的時(shí)間,又如下圖

這樣的情況下Timer則不能滿足需求。

2.Timer的時(shí)間間隔一般是定的,但是如果要每次執(zhí)行完任務(wù)要變動(dòng)一下休眠的時(shí)間, 則需要調(diào)用Timer的Change方法。

3.Timer的休眠時(shí)間不是通過整形確定休眠的毫秒數(shù),就是用一個(gè)TimeSpan來確定,對(duì)于那種到每天多少多少時(shí)刻或者到每小時(shí)的多少分執(zhí)行一次的任務(wù)來說也不能夠完全方便使用

對(duì)于上面這三種,筆者對(duì)定時(shí)器封裝了一下,棄用了Timer,還是用回了原有的Thread,定義了一種描述重復(fù)時(shí)間的模式字符串,計(jì)算出TimeSpan,從而調(diào)用Thread的Sleep()方法來休眠。下面展示整個(gè)組件的類圖

最底下是兩個(gè)關(guān)于時(shí)間計(jì)算方面的類,兩個(gè)代理是兩種任務(wù)方法的委托,基類BaseCycleMission是周期任務(wù)的積累,實(shí)現(xiàn)了ICycle接口,主要進(jìn)行對(duì)任務(wù)線程的操控(開始,停止等),繼承他的兩個(gè)子類一個(gè)是實(shí)現(xiàn)上文第一點(diǎn)中我后來描述那種需求,一個(gè)類似于原有Timer的功能。它們各自使用不同的委托。MissionManager只是對(duì)所有周期任務(wù)的一個(gè)管理,統(tǒng)一去開啟或暫停某一類的任務(wù)。

時(shí)間計(jì)算模塊

  那首先來介紹一下定義的字符串模式?,F(xiàn)在遇到的周期是有兩種模式,

一種是每隔多長時(shí)間要執(zhí)行一次的任務(wù),這個(gè)是最普通的周期形式,以每個(gè)5分鐘為例,完整的形式是“-99--99--99 -99:05:00”,“-99”是缺省的意思,當(dāng)然還有其他簡寫的模式;

另一種是沒到什么什么時(shí)候執(zhí)行一次任務(wù),例如沒到中午12點(diǎn)為例完整的形式是“ff-ff-ff 12: ff:ff”,“ff”是默認(rèn)的形式,當(dāng)然也可以用“FF”,這里也有其他簡寫的模式。

所有字符串的模式如下表所示

  每到***時(shí)刻 每隔***時(shí)間
完整 ffff-ff-ff ff:ff:ff 或
ff-ff-ff ff:ff:ff
-99--99--99 -99:-99:-99
日期部分 ffff-ff-ff 或
ff-ff-ff
-99--99--99
時(shí)間部分 ff:ff:ff 或
ff:ff:ff
-99:-99:-99
時(shí)間簡寫 ff:ff 或
ff:ff
-99:-99

  那么時(shí)間計(jì)算模塊的處理流程是,給定了相應(yīng)的模式字符串,TimePointConverter借助正則表達(dá)式匹配出對(duì)應(yīng)的模式,返回匹配出來的年月日時(shí)分秒各個(gè)值,得出結(jié)果之后就調(diào)用SleepTimeProvider來計(jì)算出線程所要休眠的時(shí)間。下面則展示一下兩個(gè)類的部分代碼

public class TimePointConverter
{
//其他成員
private int[] DateTimeFixBuilder(string timeStr)
{
int[] result = null;
string[] dtArray = timeStr.Split();
string[] dateArray = dtArray[0].Split('-');
string[] timeArray = dtArray[1].Split(':');

uint year,month,date;
uint hour, minute, second; 
uint.TryParse(dateArray[0], out year);
uint.TryParse(dateArray[1], out month);
uint.TryParse(dateArray[2], out date);

uint.TryParse(timeArray[0], out hour);
uint.TryParse(timeArray[1], out minute);
uint.TryParse(timeArray[2], out second);

//return InnerFixBuilder(year, month, date, hour, minute, second);
result = new int[] { (int)year, (int)month, (int)date, (int)hour, (int)minute, (int)second };
return result;
}
//其他成員
}
public class SleepTimeProvider
{
//其他成員
public TimeSpan InnerFixBuilder(uint year, uint month, uint date, uint hour, uint minute, uint second)
{
uint[] uintTimeArray = new uint[6] { year, month, date, hour, minute, second };
int[] intNowArray = new int[6] 
{ 
DateTime.Now.Year,DateTime.Now.Month,DateTime.Now.Day,
DateTime.Now.Hour,DateTime.Now.Minute,DateTime.Now.Second 
};
int[] intTimeArray = new int[6];
intTimeArray[0] = uintTimeArray[0] == 0 ? -DateTime.Now.Year : (int)uintTimeArray[0];
for (int i = 1; i < uintTimeArray.Length; i++)
{
intTimeArray[i] = intTimeArray[i - 1] < 0 && uintTimeArray[i] == 0 ?
-intNowArray[i] : (int)uintTimeArray[i];
}
DateTime goalTime = new DateTime(Math.Abs(intTimeArray[0]),
Math.Abs(intTimeArray[1]),
Math.Abs(intTimeArray[2]),
Math.Abs(intTimeArray[3]),
Math.Abs(intTimeArray[4]),
Math.Abs(intTimeArray[5]));
if (goalTime < DateTime.Now)
{
int max = -1;
for (int i = intTimeArray.Length - 1; i >= 0; i--)
{
if (intTimeArray[i] < 0 && i > max)
{
max = i;
intTimeArray[i]--;
}
intTimeArray[i] = Math.Abs(intTimeArray[i]);
}
goalTime = new DateTime(Math.Abs(intTimeArray[0]),
Math.Abs(intTimeArray[1]),
Math.Abs(intTimeArray[2]),
Math.Abs(intTimeArray[3]),
Math.Abs(intTimeArray[4]),
Math.Abs(intTimeArray[5]));
}
return goalTime - DateTime.Now;
}
//其他成員
}

線程調(diào)用模塊

  線程調(diào)用模塊是任務(wù)執(zhí)行的核心部分,MissionEntiy是對(duì)線程操作的封裝,主要負(fù)責(zé)開始,停止,暫停等操作。Thread用的是后臺(tái)線程,對(duì)線程操作時(shí)也多做幾個(gè)判斷。例如暫停那個(gè)操作的定義如下

public bool Pause()
{
if (actionThread == null) return false;
if (actionThread.ThreadState == (System.Threading.ThreadState.Running | ThreadState.Background) ||
actionThread.ThreadState == (System.Threading.ThreadState.WaitSleepJoin | ThreadState.Background))
{
actionThread.Suspend();
return true;
}
return false;
}

CycleMission是真正的任務(wù)載體,里面都同樣有對(duì)線程的操作,但是又外加了一些時(shí)間處理,最核心的是讓線程的BuildMainAction方法,這個(gè)方法是計(jì)算出要休眠的時(shí)間,讓線程休眠,到點(diǎn)時(shí)調(diào)用適當(dāng)?shù)姆椒ㄎ小?/p>

public class BaseCycleMission:ICycleMission
{
//其他成員
protected void BuildMainAction(string normalCycle, string overTimeCycle, object overTimeDelegate, bool isSleepBefore,bool isInclude)
{
mainAction = () =>
{
TimeSpan sleepTime=TimeSpan.MinValue;
bool result = true;
TimePointConvert.CircleType type ;
#region 提前休眠
if (isSleepBefore)
{
type = TimePointConvert.Default.PraseType(normalCycle); 
if (type == TimePointConvert.CircleType.Interval)
sleepTime = SleepTimeProvider.Defult.InnerIntervalBuilder(
TimePointConvert.Default.ConvertCircle(normalCycle));
else
sleepTime = SleepTimeProvider.Defult.InnerFixBuilder(
TimePointConvert.Default.ConvertCircle(normalCycle));
if (sleepTime.TotalMilliseconds > 0)
Thread.Sleep(sleepTime);
}
#endregion
while (true)
{
#region 計(jì)算時(shí)間
if (isInclude)
{
if (result)
{
type = TimePointConvert.Default.PraseType(normalCycle); 
type = TimePointConvert.Default.PraseType(overTimeCycle); 
sleepTime = type == TimePointConvert.CircleType.Interval ?
SleepTimeProvider.Defult.InnerIntervalBuilder(
TimePointConvert.Default.ConvertCircle(overTimeCycle)) :
SleepTimeProvider.Defult.InnerFixBuilder(
TimePointConvert.Default.ConvertCircle(overTimeCycle));
}
}
#endregion

#region 執(zhí)行方法

if(overTimeDelegate is OverTimeCycleDelegate)
result = (overTimeDelegate as OverTimeCycleDelegate).Invoke();
else
{
(overTimeDelegate as CycleDelegate).Invoke();
result = true;
}
#endregion

#region 計(jì)算時(shí)間
if (!isInclude)
{
if (result)
{

type = TimePointConvert.Default.PraseType(normalCycle);


sleepTime = type == TimePointConvert.CircleType.Interval ?
SleepTimeProvider.Defult.InnerIntervalBuilder(
TimePointConvert.Default.ConvertCircle(normalCycle)) :
SleepTimeProvider.Defult.InnerFixBuilder(
TimePointConvert.Default.ConvertCircle(normalCycle));
}
else
{
type = TimePointConvert.Default.PraseType(overTimeCycle);

sleepTime = type == TimePointConvert.CircleType.Interval ?
SleepTimeProvider.Defult.InnerIntervalBuilder(
TimePointConvert.Default.ConvertCircle(overTimeCycle)) :
SleepTimeProvider.Defult.InnerFixBuilder(
TimePointConvert.Default.ConvertCircle(overTimeCycle));
}
}
#endregion

if (sleepTime.TotalMilliseconds > 0)
Thread.Sleep(sleepTime);
}
};
}
//其他成員
}

當(dāng)然調(diào)用不是調(diào)用這個(gè)方法,調(diào)用只是調(diào)用它兩個(gè)幾類ExceptCycleMission和IncludeCycleMission,分別代表任務(wù)執(zhí)行的時(shí)間不包括在周期里面和包括在周期里面兩種。

管理器部分

  管理器主要是一個(gè)字典集,是一個(gè)ICycleMission和字符串的字典集,里面包含了對(duì)集合里面所有元素的操作:增加,刪除,運(yùn)行,恢復(fù),暫停,停止。除了刪除和增加,其他都包含了類似下面的方法

RunAllMission()
RunAllIncludeCycleMission()
RunAllExceptCycleMission()
RunMissionAmong(params string[] missionNames)
RunMissionExcept(params string[] missionNames)

但是這堆方法里面都調(diào)用了CallAction這個(gè)方法,

private void CallAction(IEnumerable<ICycleMission> missionCollection,Action method)
{
if (missionCollection == null || method == null||missionCollection.Count()==0) return;

foreach (ICycleMission item in missionCollection)
{
method.Method.Invoke(item, null);
}
}

例如在RunAllExceptCycleMission()方法里面調(diào)用如下

public void RunAllExceptCycleMission()
{
CallAction(this.Values.Where(c => c is ExceptCycleMission), BaseCycleMission.Default.RunMission);
}

  感興趣的朋友可以測試一下本文所述實(shí)例代碼,相信會(huì)有不小的收獲!

相關(guān)文章

  • .net與javascript腳本的交互方法總結(jié)

    .net與javascript腳本的交互方法總結(jié)

    這篇文章主要介紹了.net與javascript腳本的交互方法,實(shí)例講述了.net訪問javascript的方法與javascript訪問.net的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • c#實(shí)現(xiàn)漢諾塔問題示例

    c#實(shí)現(xiàn)漢諾塔問題示例

    這篇文章主要介紹了c#實(shí)現(xiàn)漢諾塔問題示例,需要的朋友可以參考下
    2014-04-04
  • C#心跳機(jī)制客戶端的實(shí)現(xiàn)示例

    C#心跳機(jī)制客戶端的實(shí)現(xiàn)示例

    本文主要介紹了C#心跳機(jī)制客戶端,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • C#中調(diào)用Servlet示例

    C#中調(diào)用Servlet示例

    這篇文章主要介紹了C#中調(diào)用Servlet示例,本文實(shí)現(xiàn)通用消息接口使用servlet作為服務(wù)器端服務(wù)接口,第三方應(yīng)用程序通過http post的方式調(diào)用servlet,實(shí)現(xiàn)與通用消息接口的調(diào)用連接,需要的朋友可以參考下
    2015-05-05
  • C#如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉

    C#如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉

    多進(jìn)程開發(fā)經(jīng)常會(huì)遇到主進(jìn)程關(guān)閉,子進(jìn)程需要跟隨主進(jìn)程一同關(guān)閉,比如調(diào)ffmpeg命令行實(shí)現(xiàn)的錄屏程序等,下面我們就來看看C#是如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉的吧
    2024-04-04
  • 那些年,我還在學(xué)習(xí)C# 學(xué)習(xí)筆記

    那些年,我還在學(xué)習(xí)C# 學(xué)習(xí)筆記

    那些年學(xué)了ASP.NET后,才開始學(xué)習(xí)C#,說來也怪,怎么學(xué)了ASP.NET才來學(xué)習(xí)C#,其實(shí)沒有什么的
    2012-03-03
  • c#實(shí)現(xiàn)在圖上畫漢字

    c#實(shí)現(xiàn)在圖上畫漢字

    這篇文章主要介紹了c#實(shí)現(xiàn)在圖上畫漢字方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼

    C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼

    本文主要介紹了C#獲取微信小程序的云數(shù)據(jù)庫中數(shù)據(jù)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C#多線程的相關(guān)操作講解

    C#多線程的相關(guān)操作講解

    本文詳細(xì)講解了C#多線程的相關(guān)操作,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • C# WPF實(shí)現(xiàn)動(dòng)態(tài)3D光照效果

    C# WPF實(shí)現(xiàn)動(dòng)態(tài)3D光照效果

    這篇文章主要為大家詳細(xì)介紹了如何利用C# WPF實(shí)現(xiàn)動(dòng)態(tài)3D的光照效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03

最新評(píng)論

开鲁县| 海南省| 绥芬河市| 万载县| 隆安县| 玛纳斯县| 泾川县| 九江市| 丹东市| 四平市| 沁源县| 怀来县| 高青县| 昭通市| 什邡市| 施甸县| 射洪县| 杭锦旗| 涞水县| 泗洪县| 浑源县| 安宁市| 康定县| 安庆市| 航空| 土默特左旗| 黎平县| 武乡县| 永吉县| 沙洋县| 栾川县| 西盟| 聂拉木县| 石林| 抚顺县| 渭源县| 庆城县| 乌恰县| 大关县| 隆昌县| 枝江市|