C#開發系統服務時用的定時器元件(修正版)
阿新 • • 發佈:2019-01-02
// 相較上一版本改進
// 1. 修改Bug
// 當設定每月一次頻率時,設定的Day日期如果為31,30,29,在有些年份的有些月份會丟擲異常,因為有些月份是沒有31天的,改正之後,
// 如果設定了31天,則只有有31天的月份會執行。
// 2. 修正一年中某天的日期較驗功能。
// 3. 新增加迴圈模式
// 每個月最後一天執行一次。
// 4. 支援到秒的定時
using System; using System.Text; using System.Windows.Forms; using UpSoft.Framework.CommonFunction.WinService; namespace TestProject { /// <summary> /// 測試服務 /// </summary> public class TestServices : ServiceTimerControl { /// <summary> /// 服務程式碼 /// </summary> protected override void StartService() { // 需要處理的服務程式碼 } /// <summary> /// 時間配置策略名(可不重寫。預設讀配置檔案中的default) /// </summary> public override string ConfigName { get { return "A"; } } } } 要呼叫時,只需輸入以下程式碼 new TestServices().Start();
//時間策略配置,可選擇以下兩種之一,配置檔案,或是重寫實現基類的獲取時間策略配置
//1.程式碼重寫
/// <summary>
/// 時間策略配置
/// </summary>
/// <returns></returns>
protected override TimerConfig GetTimerConfig()
{
return new TimerConfig{ TimerMode=..., ...};
}
//2.配置檔案實現
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="ServiceTimerConfig" type="UpSoft.Framework.CommonFunction.WinService.ServiceTimerConfigManager,CommonFunction"></section> </configSections> <ServiceTimerConfig> <!--預設採用策略--> <Default>A</Default> <!--A配置項(全節點)--> <Config> <!--A策略--> <RefName>A</RefName> <TimerMode>Interval</TimerMode> <!--延遲開始處理(單位毫秒)可為空--> <Delay>10000</Delay> <!--檔案生成時間間隔(單位毫秒,1800000=30分鐘)--> <Interval>600000</Interval> <!--月份--> <MonthSeq></MonthSeq> <!--指定第幾天的序號--> <DaySeq></DaySeq> <!--定時配置--> <Times> <!--一天之中需要執行任務的時間點--> <TimeValue>11:20:19</TimeValue> <TimeValue>10:10:43</TimeValue> <TimeValue>19:10:28</TimeValue> </Times> </Config> <!--B配置項(輪詢策略)--> <Config> <!--B策略,每隔設定的時間執行一次--> <RefName>B</RefName> <TimerMode>Interval</TimerMode> <!--延遲開始處理(單位毫秒)--> <Delay>10000</Delay> <!--檔案生成時間間隔(單位毫秒,1800000=30分鐘)--> <Interval>600000</Interval> </Config> <!--C配置項(天設定)--> <Config> <!--C策略,每週4在配置的時間點上執行--> <RefName>C</RefName> <TimerMode>Week</TimerMode> <!--延遲開始處理(單位毫秒)--> <Delay>10000</Delay> <!--每週的星期四的以下時間執行--> <DaySeq>4</DaySeq> <!--定時配置--> <Times> <!--一天之中需要執行任務的時間點--> <TimeValue>11:20:19</TimeValue> <TimeValue>10:10:43</TimeValue> <TimeValue>19:10:28</TimeValue> </Times> </Config> <!--D配置項(月、天設定)--> <Config> <!--D策略,每年12月8號在配置的時間點上執行--> <RefName>D</RefName> <TimerMode>Month</TimerMode> <!--延遲開始處理(單位毫秒)--> <Delay>10000</Delay> <!--月份--> <MonthSeq>12</MonthSeq> <!--天數--> <DaySeq>8</DaySeq> <!--定時配置--> <Times> <!--一天之中需要執行任務的時間點--> <TimeValue>11:20:19</TimeValue> <TimeValue>10:10:43</TimeValue> <TimeValue>19:10:28</TimeValue> </Times> </Config> </ServiceTimerConfig> </configuration> // TimerMode的定義 public enum TimerMode { /// /// 輪詢方式 /// Interval = 0, /// /// 一個月中某個天數的指定時間 /// Month = 1, /// /// 一週中的周幾的指定時間 /// Week = 2, /// /// 一天中的指定時間 /// Day = 3, /// /// 一年中第幾天的指定時間 /// Year = 4, /// /// 一年中的指定日期的指定時間 /// Date = 5, /// /// 每個月倒數第N天 /// LastDayOfMonth /// /// 未設定 /// NoSet }
以下是元件的原始碼
using System; using System.Collections.Generic; using System.Configuration; using System.Text.RegularExpressions; using System.Threading; using System.Xml; namespace UpSoft.Framework.CommonFunction.WinService { /// <summary> /// 服務定時器管理 /// </summary> public abstract class ServiceTimerControl { #region 私有成員 /// <summary> /// 定時器 /// </summary> private Timer SysTimer { get; set; } /// <summary> /// 是否啟用定時器 /// </summary> private bool _EnabledTimer = true; /// <summary> /// 服務執行狀態, 0-休眠, 1-執行 /// </summary> private int _serviceStatus = 0; #endregion #region 公共屬性 /// <summary> /// 獲取服務狀態 /// </summary> public int ServiceStatus { get { return _serviceStatus; } } /// <summary> /// 定時器配置 /// </summary> public TimerConfig Config { get; set; } /// <summary> /// 時間計算類 /// </summary> public TimerControl TimerControl { get; set; } /// <summary> /// 配置名稱 /// </summary> public virtual string ConfigName { get { return ( ServiceTimerConfigManager.ServiceConfig == null ? "" : ServiceTimerConfigManager.ServiceConfig.Default ); } } #endregion /// <summary> /// 停止 /// </summary> public void Stop() { _EnabledTimer = false; if ( SysTimer != null ) SysTimer.Change( Timeout.Infinite, Timeout.Infinite ); } /// <summary> /// 開始服務 /// </summary> public void Start() { try { _EnabledTimer = true; Config = this.GetTimerConfig(); if ( Config.Delay == null ) Config.Delay = new TimeSpan( 0 ); SysTimer = new Timer( new TimerCallback( this.TimerProcess ), AppDomain.CurrentDomain, Config.Delay, this.Config.Interval ); this.Logger( LogLevel.INFO, "服務啟動成功!" ); } catch ( Exception ex ) { this.ServiceException( ex ); } } /// <summary> /// 單次執行服務程式 /// </summary> public void Process() { try { //開始處理服務 this.StartService(); } catch ( Exception ex ) { this.ServiceException( ex ); } // 處理服務執行過程中出現的異常 } /// <summary> /// 處理間隔服務 /// </summary> /// <param name="sender"></param> private void TimerProcess( object sender ) { if ( !_EnabledTimer ) return; bool TimeIsUp = true; if ( this.Config.TimerMode != TimerMode.Interval ) { // 如果定時方式不是定時輪詢的話,就構造TimerControl類,該類用來計算每次執行完程式後 // 到下次執行服務時需要休眠的時間 try { this.TimerControl = new TimerControl( this.Config ); TimeIsUp = this.TimerControl.TimeIsUp; // 獲取是否到了執行服務程式的時間了 } catch ( Exception ex ) { // 讀取配置出錯且TimerControl物件已不存在,則再丟擲異常 // 如果上一次讀取配置成功,那就就算這次的配置有問題,則也不會停止程式的執行,仍用上一次的資料做為引數 if ( this.TimerControl == null ) throw ex; } } try { if ( TimeIsUp )// 時間到了可以執行程式了 { // 服務運行了 _serviceStatus = 1; // 設定計時器,在無窮時間後再啟用(實際上就是永遠不啟動計時器了--停止計時器計時) SysTimer.Change( Timeout.Infinite, Timeout.Infinite ); //開始處理服務 this.StartService(); } } catch ( Exception ex ) { this.ServiceException( ex ); } // 處理服務執行過程中出現的異常 finally { // 如果計時器不為空,則重新設定休眠的時間 if ( SysTimer != null ) { if ( this.Config.TimerMode == TimerMode.Interval )// 定時輪詢設定 { // 重新啟用計時器 SysTimer.Change( this.Config.Interval, this.Config.Interval ); } else// 定時設定 { // 用cft類計算下一次到期的時間 TimeSpan Interval = this.TimerControl.GetNextTimeUp(); // 重新啟用計時器 SysTimer.Change( Interval, Interval ); } } _serviceStatus = 0; } } /// <summary> /// 開始服務 /// </summary> protected abstract void StartService(); /// <summary> /// 記錄日誌 /// </summary> /// <param name="level">錯誤級別</param> /// <param name="msg"></param> protected virtual void Logger( LogLevel level, string msg ) { return; } /// <summary> /// 定時器初始化 /// </summary> protected virtual TimerConfig GetTimerConfig() { var config = ServiceTimerConfigManager.ServiceConfig; if ( config != null && config.Config.Length > 0 ) { // 如果沒有配置則預設為第1個 if ( String.IsNullOrEmpty( ConfigName ) ) return config.Config[0]; else// 返回配置項 foreach ( var c in config.Config ) if ( String.Compare( c.RefName, ConfigName, true ) == 0 ) return c; } throw new Exception( "時間策略配置不正確!" ); } /// <summary> /// 系統服務錯誤 /// </summary> /// <param name="ex"></param> protected virtual void ServiceException( Exception ex ) { this.Logger( LogLevel.ERROR, "服務異常:" + ex.Message + " \r\n堆疊:" + ex.StackTrace ); } } #region 定時服務休眠計算類 /// <summary> /// 檔案生成時間配置 /// </summary> public class TimerControl { #region 私有成員 private TimerConfig Config { get; set; } #endregion #region 公共成員方法 /// <summary> /// 建構函式 /// </summary> /// <param name="config">配置引數</param> /// </param> public TimerControl( TimerConfig config ) { Config = config; if ( Config == null ) throw new Exception( "定時器時間配置異常!" ); switch ( Config.TimerMode ) { case TimerMode.Date: if ( Config.MonthSeq < 1 || Config.MonthSeq > 12 ) throw new Exception( "定時器時間配置異常(月份取值只能是1~12)!" ); var dt = new DateTime( 2012, Config.MonthSeq, 1 ); // 之所以選2012,是因為他是閏年,因此2月有29天。 var lastDay = GetLastDayByMonth( dt ); if ( Config.DaySeq < 1 || Config.DaySeq > lastDay ) throw new Exception( "定時器時間配置異常(" + Config.MonthSeq + "月份的天數取值只能是1~" + lastDay + ")!" ); break; case TimerMode.Day: break; case TimerMode.Month: if ( Config.DaySeq < 1 || Config.DaySeq > 31 ) throw new Exception( "定時器時間配置異常(天數取值只能是1~31)!" ); break; case TimerMode.Week: if ( Config.DaySeq < 0 || Config.DaySeq > 6 ) throw new Exception( "定時器時間配置異常(星期取值只能是0~6)!" ); break; case TimerMode.LastDayOfMonth: if ( Config.DaySeq != 0 ) {// 如果等於0的話,表示是每個月的最後一天。 if ( Config.DaySeq < 1 || Config.DaySeq > 28 ) throw new Exception( "定時器時間配置異常(倒數的天數只能是1~28,即倒數的第1天,第2天。。。有些月份並沒有29.30.31天,因此最大隻允許倒數第28天)!" ); Config.DaySeq -= 1; } break; case TimerMode.Year: if ( Config.DaySeq < 1 || Config.DaySeq > 366 ) throw new Exception( "定時器時間配置異常(天數取值只能是1~366)!" ); break; } } /// <summary> /// 判斷時間是否到了 /// </summary> /// <returns>true時間已經到了,false時間還未到</returns> public bool TimeIsUp { get { DateTime dt = DateTime.Now; if ( CheckTimeIsUp( dt.TimeOfDay ) ) { switch ( Config.TimerMode ) { case TimerMode.Day: return true; case TimerMode.Date: return dt.Month == Config.MonthSeq && dt.Day == Config.DaySeq; case TimerMode.Week: return ( ( int )dt.DayOfWeek ) == Config.DaySeq; case TimerMode.Month: return dt.Day == Config.DaySeq; case TimerMode.Year: return dt.DayOfYear == Config.DaySeq; case TimerMode.LastDayOfMonth: return dt.Day == ( GetLastDayByMonth( dt ) - Config.DaySeq ); default: return false; } } else return false; } } /// <summary> /// 時間是否到了 /// </summary> /// <returns></returns> private bool CheckTimeIsUp( TimeSpan time ) { var tmp = new TimeSpan( time.Hours, time.Minutes, time.Seconds ); if ( Config.Times == null ) return ( tmp.Ticks == 0 ); else { foreach ( var t in Config.Times ) { if ( t == tmp ) return true; } return false; } } /// <summary> /// 從現在起到下次時間到還有多少時間 /// </summary> /// <returns>時間間隔</returns> public TimeSpan GetNextTimeUp() { ///目標時間 DateTime _NextDateTime = this.GetNextDateTime(); // 儲存下一次要執行的時間 return _NextDateTime - DateTime.Now; } /// <summary> /// 獲取下一次指定配置的時間是多少 /// </summary> /// <returns></returns> public DateTime GetNextDateTime() { var time = GetNextTimeConfig(); DateTime dt = DateTime.Now; DateTime now, target; switch ( Config.TimerMode ) { case TimerMode.Day: #region 每天指定某時執行一次 now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, dt.Second ); target = new DateTime( 1, 1, 1, time.Hours, time.Minutes, time.Seconds ); if ( now.Ticks >= target.Ticks ) dt = dt.AddDays( 1.0 ); //如果當前時間小於指定時刻,則不需要加天 dt = new DateTime( dt.Year, dt.Month, dt.Day, time.Hours, time.Minutes, time.Seconds ); #endregion break; case TimerMode.Month: #region 每月指定某天某時執行一次 now = new DateTime( 1, 1, dt.Day, dt.Hour, dt.Minute, dt.Second ); target = new DateTime( 1, 1, Config.DaySeq, time.Hours, time.Minutes, time.Seconds ); // 1月有31天,所以可以接受任何合法的Day值(因為在賦值時已判斷1~31) if ( now.Ticks >= target.Ticks ) dt = dt.AddMonths( 1 ); // 當前月份的指定天數執行過了,因此月份加上一個月,當月份加了一個月之後,很可能當前實現的Day值可能會變小(例:3月31號,加上一個月,則日期會變成,4月30號,而不會變成5月1號), // 因此需要判斷指定的this.Day是不是比Day大(月份的Day變小的唯一原因是因為月份加了一個月之後,那個月並沒有this.Day的天數),如果沒有該this.Day的天數。則需要為該月份再加一個月。 // 加一個月份,則那下個月一定可以大於等於this.Day, 看看每個月的天數就可以斷定了, // 因為沒有連著兩個月的日期小於等於30的,只有連續兩個月是31天。其它就是間隔的出現(this.Day最大隻可能為31) // 如此之後,接下來的dt=new DateTime時不為因為dt.Month的月份,因沒有this.Day天數而拋異常 if ( Config.DaySeq > GetLastDayByMonth( dt ) ) dt = dt.AddMonths( 1 ); // 如此是為了確保dt.Month的月份一定有this.Day天(因此如果設定為每個月的31號執行的程式,就只會在1,3,5,7,8,10,12幾個月份會執行) dt = new DateTime( dt.Year, dt.Month, Config.DaySeq, time.Hours, time.Minutes, time.Seconds ); #endregion break; case TimerMode.LastDayOfMonth: #region 每個月倒數第N天的某時某刻執行一次 var lastDaybymonth = GetLastDayByMonth( dt ) - Config.DaySeq; now = new DateTime( 1, 1, dt.Day, dt.Hour, dt.Minute, dt.Second ); target = new DateTime( 1, 1, lastDaybymonth, time.Hours, time.Minutes, time.Seconds ); // 1月有31天,所以可以接受任何合法的Day值(因為在賦值時已判斷1~31) if ( now.Ticks >= target.Ticks ) { dt = dt.AddMonths( 1 ); dt = new DateTime( dt.Year, dt.Month, GetLastDayByMonth( dt ) - Config.DaySeq, time.Hours, time.Minutes, time.Seconds );// 根據新月份求新月份的最後一天。 } else dt = new DateTime( dt.Year, dt.Month, lastDaybymonth, time.Hours, time.Minutes, time.Seconds ); #endregion break; case TimerMode.Week: #region 每星期指定星期某時執行一次 int dow = ( int )dt.DayOfWeek; now = new DateTime( 1, 1, dow + 1, dt.Hour, dt.Minute, dt.Second ); target = new DateTime( 1, 1, Config.DaySeq + 1, time.Hours, time.Minutes, time.Seconds ); if ( now.Ticks >= target.Ticks ) dt = dt.AddDays( Config.DaySeq - dow + 7 ); else dt = dt.AddDays( Config.DaySeq - dow ); dt = new DateTime( dt.Year, dt.Month, dt.Day, time.Hours, time.Minutes, time.Seconds ); #endregion break; case TimerMode.Date: #region 每年指定某月某日某時執行一次 now = new DateTime( 4, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second ); // 0004年閏年,可以支援2月29.因此選了0004, 這樣就不會在構造Target時異常, // 因為比較的關鍵不在年。所以,只要Now和Target的年份一樣就可以,設定成什麼年份無所謂 target = new DateTime( 4, Config.MonthSeq, Config.DaySeq, time.Hours, time.Minutes, time.Seconds ); if ( now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 ); if ( Config.MonthSeq == 2 && Config.DaySeq == 29 ) { // 因為閏年的最大間隔是8年,平時是4年一閏,可是0096年閏完之後,下一個閏年就是0104年,因此。。。 for ( int i = 0; i < 8; i++ ) if ( DateTime.IsLeapYear( dt.Year + i ) ) { dt = dt.AddYears( i ); break; } } dt = new DateTime( dt.Year, Config.MonthSeq, Config.DaySeq, time.Hours, time.Minutes, time.Seconds ); #endregion break; case TimerMode.Year: #region 每年指定第N天某時執行一次 now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, dt.Second ); target = new DateTime( 1, 1, 1, time.Hours, time.Minutes, time.Seconds ); if ( dt.DayOfYear > Config.DaySeq || dt.DayOfYear == Config.DaySeq && now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 ); dt = dt.AddDays( Config.DaySeq - dt.DayOfYear ); dt = new DateTime( dt.Year, dt.Month, dt.Day, time.Hours, time.Minutes, time.Seconds ); #endregion break; default: throw new Exception( "定時器時間配置異常!" ); } return dt; } /// <summary> /// 獲取指定日期所在月份的最後一天 /// </summary> /// <param name="dt"></param> /// <returns></returns> private int GetLastDayByMonth( DateTime dt ) { switch ( dt.Month ) { case 4: case 6: case 9: case 11: return 30; case 2: return DateTime.IsLeapYear( dt.Year ) ? 29 : 28; default: return 31; } } /// <summary> /// 獲取下一個時間點 /// </summary> /// <returns></returns> private TimeSpan GetNextTimeConfig() { if ( Config.Times == null || Config.Times.Length == 0 ) return new TimeSpan( 0 ); else { var minData = TimeSpan.MaxValue; // 最小時間 var minExecData = TimeSpan.MaxValue; // 大於當前時間的最小時間 foreach ( var t in Config.Times ) { if ( DateTime.Now.TimeOfDay < t && minExecData >= t ) // 找出比當前時間大的最小時間 minExecData = t; if ( minData > t ) // 找出最小的一個時間,當前時間不參與運算 minData = t; } if ( minExecData == TimeSpan.MaxValue ) // 如果找不到比當前時間大的最小時間,則選擇最小時間返回 return minData; else return minExecData; } } #endregion } #endregion #region 系統配置實體類&配置讀取類 /// <summary> /// 時間配置類 /// </summary> public class ServiceTimerConfig { /// <summary> /// 預設配置 /// </summary> public string Default { get; set; } /// <summary> /// 配置項 /// </summary> public TimerConfig[] Config { get; set; } } /// <summary> /// 時間配置 /// </summary> public class TimerConfig { /// <summary> /// 配置引用名 /// </summary> public string RefName { get; set; } /// <summary> /// 時間模式 /// timeMode取值如下:TimerMode.Month、TimerMode.Week、TimerMode.Week、TimerMode.Day、TimerMode.Date、TimerMode.Year /// </summary> public TimerMode TimerMode { get; set; } /// <summary> /// 指定某個時間演算法的第幾天,第1天就為1 /// TimerMode=TimerMode.Month 時, 該DaySeq表示每個月中的第幾天 /// TimerMode=TimerMode.Week 時, 該DaySeq表示每個星期中的星期幾(0-星期天,其它用1-6表示) /// TimerMode=TimerMode.Day 時, 該值不需要設定 /// TimerMode=TimerMode.Date 時, 該DaySeq表示每個日期中的天數,如:8月12號,則DaySeq為12,MonthSeq為8 /// TimerMode=TimerMode.LastDayOfMonth 時, 該DaySeq表示每個月倒數第幾天 /// TimerMode=TimerMode.Year 時, 該DaySeq表示每年中的第幾天 /// </summary> public int DaySeq { get; set; } /// <summary> /// 當指定一年中某個月的某個日期時有用到如:指定一年中8月12號,則這裡的MonthSeq就應該為8 /// </summary> public int MonthSeq { get; set; } /// <summary> /// 迴圈處理時間間隔(單位毫秒) /// </summary> public TimeSpan Interval { get; set; } /// <summary> /// 啟動延遲時間(單位毫秒) /// </summary> public TimeSpan Delay { get; set; } /// <summary> /// 時間設定 /// </summary> public TimeSpan[] Times { get; set; } } /// <summary> /// 服務處理方法 /// </summary> public enum TimerMode { /// <summary> /// 輪詢方式 /// </summary> Interval = 0, /// <summary> /// 一個月中某個天數的指定時間 /// </summary> Month = 1, /// <summary> /// 一週中的周幾的指定時間 /// </summary> Week = 2, /// <summary> /// 一天中的指定時間 /// </summary> Day = 3, /// <summary> /// 一年中第幾天的指定時間 /// </summary> Year = 4, /// <summary> /// 一年中的指定日期的指定時間 /// </summary> Date = 5, /// <summary> /// 每個月倒數第N天 /// </summary> LastDayOfMonth, /// <summary> /// 未設定 /// </summary> NoSet } /// <summary> /// 讀取配置資料 /// </summary> public class ServiceTimerConfigManager : IConfigurationSectionHandler { private static Regex regEx = new Regex( @"^(?<h>[01]?\d|2[0-3])(?:[::](?<m>[0-5]\d?))?(?:[::](?<s>[0-5]\d?))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase ); /// <summary> /// 請求服務配置 /// </summary> public static ServiceTimerConfig ServiceConfig { get; set; } /// <summary> /// 靜態建構函式 /// </summary> static ServiceTimerConfigManager() { ConfigurationManager.GetSection( "ServiceTimerConfig" ); } /// <summary> /// 讀取自定義配置節 /// </summary> /// <param name="parent">父結點</param> /// <param name="configContext">配置上下文</param> /// <param name="section">配置區</param> /// <returns></returns> object IConfigurationSectionHandler.Create( object parent, object configContext, XmlNode section ) { ServiceConfig = new ServiceTimerConfig(); var config = new List<TimerConfig>(); foreach ( XmlNode node in section.ChildNodes ) { if ( node.NodeType == XmlNodeType.Element ) { switch ( node.Name.ToLower() ) { case "default": ServiceConfig.Default = node.InnerText; break; ; case "config": var tmp = new TimerConfig(); SetTimerConfigValue( tmp, node ); config.Add( tmp ); break; ; } } } ServiceConfig.Config = config.ToArray(); return ServiceConfig; } /// <summary> /// 設定定時器值 /// </summary> /// <param name="Config"></param> /// <param name="node"></param> private void SetTimerConfigValue( TimerConfig Config, XmlNode node ) { int tmp, h, m, s; long longTmp; var times = new List<TimeSpan>(); foreach ( XmlNode xn in node.ChildNodes ) { if ( xn.NodeType == XmlNodeType.Element ) { switch ( xn.Name.ToLower() ) { case "refname": Config.RefName = xn.InnerText; break; case "timermode": if ( xn.InnerText != null ) Config.TimerMode = ( TimerMode )Enum.Parse( typeof( TimerMode ), xn.InnerText ); break; case "delay": Int64.TryParse( xn.InnerText, out longTmp ); Config.Delay = new TimeSpan( longTmp * 10 * 1000L ); // Delay配置值為毫秒 break; case "interval": Int64.TryParse( xn.InnerText, out longTmp ); // Interval配置值為毫秒 Config.Interval = new TimeSpan( longTmp * 10 * 1000L ); break; case "monthseq": // 月份 Int32.TryParse( xn.InnerText, out tmp ); Config.MonthSeq = tmp; break; case "dayseq": // 指定第幾天的序號 Int32.TryParse( xn.InnerText, out tmp ); Config.DaySeq = tmp; break; case "times": //還是用這個函式處理下一級的配置 SetTimerConfigValue( Config, xn ); // 設定時間策略 break; case "timevalue": var mc = regEx.Match( xn.InnerText ); if ( !mc.Success ) throw new Exception( "時間配置不正確!" ); Int32.TryParse( mc.Groups["h"].Value, out h ); Int32.TryParse( mc.Groups["m"].Value, out m ); Int32.TryParse( mc.Groups["s"].Value, out s ); times.Add( new TimeSpan( h, m, s ) ); break; } } } if ( times.Count != 0 ) Config.Times = times.ToArray(); } } #endregion }