现在的位置: 首页 > 综合 > 正文

C#开发系统服务时用的定时器组件

2012年11月26日 ⁄ 综合 ⁄ 共 17708字 ⁄ 字号 评论关闭

转自http://blog.csdn.net/linux7985/article/details/5843394

写服务时,都需要为定时器写不少的代码,感觉很麻烦,今天把这些代码封装一下,希望能简化一下这方面的工作,把精力都集中在功能上

本定时器组件,每次只启动一个服务实例进行处理,而不会同时多次执行服务代码。

 

下面是应用实例

从组件类派生一个子类,可以看到,需要写的代码很少

 

[c-sharp] view plaincopy
  1. using System;     
  2. using System.Collections.Generic;     
  3. using System.IO;     
  4. using System.Text.RegularExpressions;     
  5. using System.Threading;  
  6.     
  7. namespace BlueVision.SaYuan.WinService     
  8. {     
  9.     public class TestService : ServiceTimerContorl     
  10.     {     
  11.         protected override void StartService()     
  12.         {     
  13.             //需要做的事情的代码     
  14.         }     
  15.     
  16.         protected override ServiceTimeConfig GetTimerConfig()     
  17.         {     
  18.             ServiceTimeConfig config = new ServiceTimeConfig();     
  19.     
  20.             // 如果该枚举是选择 Interval ,则表示,上述的 StartService 方法,将隔 config.ChkInterval 毫秒执行一次     
  21.             config.TimerMode = TimerMode.Interval;     
  22.             config.ChkInterval = 100000;     
  23.     
  24.     
  25.             /// StartTime值为:     
  26.             ///      
  27.             /// TimerMode=TimerMode.Month   "09|04:30"  -表示每月9号的凌晨4点30分     
  28.             /// TimerMode=TimerMode.Week     "0|04:30"  -表示每星期天的4点30分     
  29.             /// TimerMode=TimerMode.Week     "6|04:00"  -表示每星期6的4点30分     
  30.             /// TimerMode=TimerMode.Day       "|04:00"  -表示每天的4点00分     
  31.             /// TimerMode=TimerMode.Date "08-10|04:00"  -表示每年8月10号的4点00分执行一次     
  32.             /// TimerMode=TimerMode.Year   "246|04"     -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)     
  33.     
  34.             //如果是这样设置 则表示,每天的凌晨 4 点 00 执行一次     
  35.             config.TimerMode = TimerMode.Day;     
  36.             config.StartTime = "|04";     
  37.     
  38.             //如果是这样设置 则表示,每个星期的星期四那天的凌晨 6 点 35 执行一次     
  39.             config.TimerMode = TimerMode.Week;     
  40.             config.StartTime = "4|06:35";     
  41.     
  42.             //如果是这样设置 则表示,每个星期的星期天那天的凌晨 6 点 00 执行一次     
  43.             config.TimerMode = TimerMode.Week;     
  44.             config.StartTime = "0|06";     
  45.     
  46.             //如果是这样设置 则表示,每个月的9号凌晨 6 点 28 执行一次     
  47.             config.TimerMode = TimerMode.Month;     
  48.             config.StartTime = "09|06:28";     
  49.     
  50.             //如果是这样设置 则表示,每年8月10号的4点00分执行一次     
  51.             config.TimerMode = TimerMode.Date;     
  52.             config.StartTime = "08-10|04:00";     
  53.     
  54.             //如果是这样设置 则表示,每年第246天的4点27分执行一次     
  55.             config.TimerMode = TimerMode.Year;     
  56.             config.StartTime = "246|04:27";     
  57.     
  58.             return config;     
  59.         }     
  60.         /// <summary>     
  61.         /// 当服务出错时,处理     
  62.         /// </summary>     
  63.         /// <param name="ex"></param>     
  64.         protected override void  ServiceException(Exception ex)     
  65.         {     
  66.              //可以不实现     
  67.         }     
  68.     }     
  69. }     
  70.     
  71.     
  72. //要执行代码,以下这样就可以了  
  73. TestService testService = new TestService();     
  74. testService.Start();   

 

 

以下是组件的源代码

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.IO;  
  4. using System.Text.RegularExpressions;  
  5. using System.Threading;  
  6.   
  7. namespace BlueVision.SaYuan.WinService  
  8. {  
  9.     /// <summary>  
  10.     /// 服务定时器管理  
  11.     /// </summary>  
  12.     public abstract class ServiceTimerControl  
  13.     {  
  14.         #region 私有成员  
  15.         /// <summary>  
  16.         /// 定时器  
  17.         /// </summary>  
  18.         private Timer SysTimer { get; set; }  
  19.         /// <summary>  
  20.         /// 是否启用定时器  
  21.         /// </summary>  
  22.         private bool _EnabledTimer = true;  
  23.         /// <summary>  
  24.         /// 服务执行状态  
  25.         /// </summary>  
  26.         private ServiceStatus _serviceStatus = ServiceStatus.Sleep;  
  27.         /// <summary>  
  28.         /// 时间计算类  
  29.         /// </summary>  
  30.         private TimerControl _timerControl = null;  
  31.         /// <summary>  
  32.         /// 定时器配置  
  33.         /// </summary>  
  34.         ServiceTimeConfig Config;  
  35.         #endregion  
  36.  
  37.         #region 公共属性  
  38.         /// <summary>  
  39.         /// 获取服务状态  
  40.         /// </summary>  
  41.         public ServiceStatus ServiceStatus { get { return _serviceStatus; } }  
  42.         /// <summary>  
  43.         /// 计时模式  
  44.         /// </summary>  
  45.         public TimerMode TimerMode  
  46.         {  
  47.             get  
  48.             {  
  49.                 if ( Config == null ) Config = this.GetTimerConfig();  
  50.   
  51.                 return Config.TimerMode;  
  52.             }  
  53.         }  
  54.         /// <summary>  
  55.         /// 计时配置  
  56.         /// </summary>  
  57.         public string StartTime { get { return ( Config == null ) ? "" : Config.StartTime; } }  
  58.         /// <summary>  
  59.         /// 时间计算类  
  60.         /// </summary>  
  61.         public TimerControl TimerControl  
  62.         {  
  63.             get  
  64.             {  
  65.                 if ( Config == null )  
  66.                     Config = this.GetTimerConfig();  
  67.                 if ( _timerControl == null )  
  68.                     _timerControl = new TimerControl( this.Config.StartTime, this.Config.TimerMode );  
  69.   
  70.                 return _timerControl;  
  71.             }  
  72.         }  
  73.         #endregion  
  74.   
  75.         /// <summary>  
  76.         /// 停止  
  77.         /// </summary>  
  78.         public void Stop()  
  79.         {  
  80.             _EnabledTimer = false;  
  81.   
  82.             SysTimer.Change( Timeout.Infinite, Timeout.Infinite );  
  83.         }  
  84.         /// <summary>  
  85.         /// 开始服务  
  86.         /// </summary>  
  87.         public void Start()  
  88.         {  
  89.             _EnabledTimer = true;  
  90.             Config = this.GetTimerConfig();  
  91.   
  92.             SysTimer = new Timer( new TimerCallback( this.TimerProcess ), AppDomain.CurrentDomain, 0, this.Config.ChkInterval );  
  93.         }  
  94.         /// <summary>  
  95.         /// 处理间隔服务  
  96.         /// </summary>  
  97.         /// <param name="sender"></param>  
  98.         private void TimerProcess( object sender )  
  99.         {  
  100.             if ( !_EnabledTimer ) return;  
  101.   
  102.             bool TimeIsUp = true;  
  103.             if ( this.Config.TimerMode != TimerMode.Interval )  
  104.             {  
  105.                 // 如果定时方式不是定时轮询的话,就构造TimerControl类,该类用来计算每次执行完程序后  
  106.                 // 到下次执行服务时需要休眠的时间  
  107.                 try  
  108.                 {  
  109.                     _timerControl = new TimerControl( this.Config.StartTime, this.Config.TimerMode );  
  110.                     TimeIsUp = _timerControl.TimeIsUp;  // 获取是否到了执行服务程序的时间了  
  111.                 }  
  112.                 catch ( Exception ex )  
  113.                 {  
  114.                     // 读取配置出错且TimerControl对象已不存在,则再抛出异常  
  115.                     // 如果上一次读取配置成功,那就就算这次的配置有问题,则也不会停止程序的运行,仍用上一次的数据做为参数  
  116.                     if ( _timerControl == null ) throw ex;  
  117.                 }  
  118.             }  
  119.   
  120.             try  
  121.             {  
  122.                 if ( TimeIsUp )// 时间到了可以执行程序了  
  123.                 {  
  124.                     // 服务运行了  
  125.                     _serviceStatus = ServiceStatus.Running;  
  126.   
  127.                     // 设置计时器,在无穷时间后再启用(实际上就是永远不启动计时器了--停止计时器计时)  
  128.                     SysTimer.Change( Timeout.Infinite, this.Config.ChkInterval );  
  129.   
  130.                     //开始处理服务  
  131.                     this.StartService();  
  132.                 }  
  133.             }  
  134.             catch ( Exception ex ) { this.ServiceException( ex ); } // 处理服务执行过程中出现的异常  
  135.             finally  
  136.             {  
  137.                 // 如果计时器不为空,则重新设置休眠的时间  
  138.                 if ( SysTimer != null )  
  139.                 {  
  140.                     if ( this.Config.TimerMode == TimerMode.Interval )// 定时轮询设置  
  141.                     {  
  142.                         // 重新启用计时器  
  143.                         SysTimer.Change( this.Config.ChkInterval, this.Config.ChkInterval );  
  144.                     }  
  145.                     else// 定时设置  
  146.                     {  
  147.                         // 用cft类计算下一次到期的时间  
  148.                         TimeSpan Interval = _timerControl.GetNextTimeUp();  
  149.                         // 重新启用计时器  
  150.                         SysTimer.Change( Interval, Interval );  
  151.                     }  
  152.                 }  
  153.                 _serviceStatus = ServiceStatus.Sleep;  
  154.             }  
  155.         }  
  156.         /// <summary>  
  157.         /// 开始服务  
  158.         /// </summary>  
  159.         protected abstract void StartService();  
  160.         /// <summary>  
  161.         /// 定时器初始化  
  162.         /// </summary>  
  163.         /// <param name="TimerMode"></param>  
  164.         /// <param name="StartTime"></param>  
  165.         /// <param name="ChkInterval"></param>  
  166.         protected abstract ServiceTimeConfig GetTimerConfig();  
  167.         /// <summary>  
  168.         /// 系统服务错误  
  169.         /// </summary>  
  170.         /// <param name="ex"></param>  
  171.         protected virtual void ServiceException( Exception ex ) { return; }  
  172.     }  
  173.  
  174.     #region 定时器相关实体类  
  175.     /// <summary>  
  176.     /// 服务定时器配置  
  177.     /// </summary>  
  178.     public class ServiceTimeConfig  
  179.     {  
  180.         /// <summary>  
  181.         /// 轮询目录时间间隔(单位:毫秒)  
  182.         /// </summary>  
  183.         public int ChkInterval { get; set; }  
  184.         /// <summary>  
  185.         /// StartTime值为:  
  186.         ///   
  187.         /// TimerMode=TimerMode.Month   "09|04:30"  -表示每月9号的凌晨4点30分  
  188.         /// TimerMode=TimerMode.Week     "0|04:30"  -表示每星期天的4点30分  
  189.         /// TimerMode=TimerMode.Week     "6|04:00"  -表示每星期6的4点30分  
  190.         /// TimerMode=TimerMode.Day       "|04:00"  -表示每天的4点00分  
  191.         /// TimerMode=TimerMode.Date "08-10|04:00"  -表示每年8月10号的4点00分执行一次  
  192.         /// TimerMode=TimerMode.Year   "246|04"     -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)  
  193.         /// </summary>  
  194.         public string StartTime { get; set; }  
  195.         /// <summary>  
  196.         /// 服务器定时处理模型  
  197.         /// </summary>  
  198.         public TimerMode TimerMode { get; set; }  
  199.     }  
  200.     /// <summary>  
  201.     /// 服务处理方法  
  202.     /// </summary>  
  203.     public enum TimerMode  
  204.     {  
  205.         /// <summary>  
  206.         /// 轮询方式  
  207.         /// </summary>  
  208.         Interval = 0,  
  209.         /// <summary>  
  210.         /// 一个月中某个天数的指定时间  
  211.         /// </summary>  
  212.         Month = 1,  
  213.         /// <summary>  
  214.         /// 一周中的周几的指定时间  
  215.         /// </summary>  
  216.         Week = 2,  
  217.         /// <summary>  
  218.         /// 一天中的指定时间  
  219.         /// </summary>  
  220.         Day = 3,  
  221.         /// <summary>  
  222.         /// 一年中第几天的指定时间  
  223.         /// </summary>  
  224.         Year = 4,  
  225.         /// <summary>  
  226.         /// 一年中的指定日期的指定时间  
  227.         /// </summary>  
  228.         Date = 5,  
  229.         /// <summary>  
  230.         /// 未设置  
  231.         /// </summary>  
  232.         NoSet  
  233.     }  
  234.     /// <summary>  
  235.     /// 服务处理方法  
  236.     /// </summary>  
  237.     public enum ServiceStatus  
  238.     {  
  239.         /// <summary>  
  240.         /// 休眠中  
  241.         /// </summary>  
  242.         Sleep = 0,  
  243.         /// <summary>  
  244.         /// 服务在执行过程中  
  245.         /// </summary>  
  246.         Running = 1  
  247.     }  
  248.     #endregion  
  249.  
  250.     #region 定时服务休眠时间计算类  
  251.     /// <summary>  
  252.     /// 定时服务休眠时间计算类  
  253.     /// </summary>  
  254.     public class TimerControl  
  255.     {  
  256.         #region 私有成员  
  257.         /// <summary>  
  258.         /// 间隔单位  
  259.         /// </summary>  
  260.         private TimerMode type;  
  261.         /// <summary>  
  262.         /// 月份  
  263.         /// </summary>  
  264.         private int Month;  
  265.         /// <summary>  
  266.         /// 天  
  267.         /// </summary>  
  268.         private int Day;  
  269.         /// <summary>  
  270.         /// 小时  
  271.         /// </summary>  
  272.         private int Hour;  
  273.         /// <summary>  
  274.         /// 分钟  
  275.         /// </summary>  
  276.         private int Minute = 0;  
  277.         #endregion  
  278.  
  279.         #region 公共成员方法  
  280.         /// <summary>  
  281.         /// StartTime值为:  
  282.         ///   
  283.         /// TimerMode=TimerMode.Month   "09|04:30"  -表示每月9号的凌晨4点30分  
  284.         /// TimerMode=TimerMode.Week     "0|04:30"  -表示每星期天的4点30分  
  285.         /// TimerMode=TimerMode.Week     "6|04:00"  -表示每星期6的4点30分  
  286.         /// TimerMode=TimerMode.Day       "|04:00"  -表示每天的4点00分  
  287.         /// TimerMode=TimerMode.Date "08-10|04:00"  -表示每年8月10号的4点00分执行一次  
  288.         /// TimerMode=TimerMode.Year   "246|04"     -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)  
  289.         /// </summary>  
  290.         /// <param name="StartTime"></param>  
  291.         /// <param name="timeMode"></param>  
  292.         public TimerControl( string StartTime, TimerMode timeMode )  
  293.         {  
  294.             //Regex regEx = new Regex( @"(?<Type>[MWDY])(?<Days>/d+)?/|(?<Hour>/d+):?(?<Minute>[0-5]/d?)?", RegexOptions.Compiled | RegexOptions.IgnoreCase );  
  295.             Regex regEx = new Regex( @"^(?:(?<Month>[0]?/d|1[0-2])-)?(?<Days>/d{1,3})?/|(?<Hour>[01]?/d|2[0-3])(?::(?<Minute>[0-5]/d?))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase );  
  296.   
  297.             this.type = timeMode;  
  298.   
  299.             Match m = regEx.Match( StartTime );  
  300.             if ( m.Success )  
  301.             {  
  302.                 if ( String.IsNullOrEmpty( m.Groups["Month"].Value ) && this.type == TimerMode.Date )  
  303.                     throw new Exception( "定时器时间配置异常!" );  
  304.   
  305.                 if ( !String.IsNullOrEmpty( m.Groups["Month"].Value ) )  
  306.                     this.Month = Convert.ToInt32( m.Groups["Month"].Value );  
  307.   
  308.                 if ( !String.IsNullOrEmpty( m.Groups["Days"].Value ) )  
  309.                     this.Day = Convert.ToInt32( m.Groups["Days"].Value );  
  310.   
  311.                 this.Hour = Convert.ToInt32( m.Groups["Hour"].Value );  
  312.   
  313.                 if ( !String.IsNullOrEmpty( m.Groups["Minute"].Value ) )  
  314.                     this.Minute = Convert.ToInt32( m.Groups["Minute"].Value );  
  315.             }  
  316.             else  
  317.                 throw new Exception( "定时器时间配置异常!" );  
  318.         }  
  319.         /// <summary>  
  320.         /// 判断时间是否到了  
  321.         /// </summary>  
  322.         /// <returns></returns>  
  323.         public bool TimeIsUp  
  324.         {  
  325.             get  
  326.             {  
  327.                 DateTime dt = DateTime.Now;  
  328.                 switch ( type )  
  329.                 {  
  330.                     case TimerMode.Day:  
  331.                         return ( dt.Hour == this.Hour && dt.Minute == this.Minute );  
  332.                     case TimerMode.Month:  
  333.                         return ( dt.Day == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );  
  334.                     case TimerMode.Week:  
  335.                         return ( ( ( int )dt.DayOfWeek ) == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );  
  336.                     case TimerMode.Date:  
  337.                         return ( dt.Month == this.Month && dt.Day == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );  
  338.                     case TimerMode.Year:  
  339.                         return ( dt.DayOfYear == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );  
  340.                 }  
  341.                 return false;  
  342.             }  
  343.         }  
  344.         /// <summary>  
  345.         /// 从现在起到下次时间到还有多少时间  
  346.         /// </summary>  
  347.         /// <returns></returns>  
  348.         public TimeSpan GetNextTimeUp()  
  349.         {  
  350.             ///目标时间  
  351.             DateTime _NextDateTime = this.GetNextDateTime();    // 保存下一次要执行的时间  
  352.             TimeSpan NextCrtFileTime = _NextDateTime - DateTime.Now;  
  353.   
  354.             if ( ( int )NextCrtFileTime.TotalMilliseconds > int.MaxValue )   // 如果要休眠的时间间隔超过int类型可以表示的毫秒时,先休眠到int.MaxValue,然后再次休眠  
  355.                 NextCrtFileTime = new TimeSpan( int.MaxValue );  
  356.   
  357.             return NextCrtFileTime;  
  358.         }  
  359.         /// <summary>  
  360.         /// 获取下一次指定配置的时间是多少  
  361.         /// </summary>  
  362.         /// <returns></returns>  
  363.         public DateTime GetNextDateTime()  
  364.         {  
  365.             DateTime dt = DateTime.Now;  
  366.             DateTime now, target;  
  367.             switch ( this.type )  
  368.             {  
  369.                 case TimerMode.Day:  
  370.                     #region 每天指定某时执行一次  
  371.                     now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, 0 );  
  372.                     target = new DateTime( 1, 1, 1, this.Hour, this.Minute, 0 );  
  373.                     if ( now.Ticks >= target.Ticks ) dt = dt.AddDays( 1.0 ); //如果当前时间小于指定时刻,则不需要加天  
  374.   
  375.                     dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );  
  376.                     #endregion  
  377.                     break;  
  378.                 case TimerMode.Month:  
  379.                     #region 每月指定某天某时执行一次  
  380.                     now = new DateTime( 1, 1, dt.Day, dt.Hour, dt.Minute, 0 );  
  381.                     target = new DateTime( 1, 1, this.Day, this.Hour, this.Minute, 0 );  
  382.                     if ( now.Ticks >= target.Ticks ) dt = dt.AddMonths( 1 );  
  383.   
  384.                     dt = new DateTime( dt.Year, dt.Month, this.Day, this.Hour, this.Minute, 0 );  
  385.                     #endregion  
  386.                     break;  
  387.                 case TimerMode.Week:  
  388.                     #region 每星期指定星期某时执行一次  
  389.                     int dow = ( int )dt.DayOfWeek;  
  390.                     now = new DateTime( 1, 1, dow + 1, dt.Hour, dt.Minute, 0 );  
  391.                     target = new DateTime( 1, 1, this.Day + 1, this.Hour, this.Minute, 0 );  
  392.   
  393.                     if ( now.Ticks >= target.Ticks )  
  394.                         dt = dt.AddDays( this.Day - dow + 7 );  
  395.                     else  
  396.                         dt = dt.AddDays( this.Day - dow );  
  397.   
  398.                     dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );  
  399.                     #endregion  
  400.                     break;  
  401.                 case TimerMode.Date:  
  402.                     #region 每年指定某月某日某时执行一次  
  403.                     now = new DateTime( 1, dt.Month, dt.Day, dt.Hour, dt.Minute, 0 );  
  404.                     target = new DateTime( 1, this.Month, this.Day, this.Hour, this.Minute, 0 );  
  405.                     if ( now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 );  
  406.   
  407.                     dt = new DateTime( dt.Year, this.Month, this.Day, this.Hour, this.Minute, 0 );  
  408.                     #endregion  
  409.                     break;  
  410.                 case TimerMode.Year:  
  411.                     #region 每年指定第N天某时执行一次  
  412.                     now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, 0 );  
  413.                     target = new DateTime( 1, 1, 1, this.Hour, this.Minute, 0 );  
  414.                     if ( dt.DayOfYear > this.Day || dt.DayOfYear == this.Day && now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 );  
  415.                     dt = dt.AddDays( this.Day - dt.DayOfYear );  
  416.   
  417.                     dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );  
  418.                     #endregion  
  419.                     break;  
  420.                 default:  
  421.                     throw new Exception( "定时器时间配置异常!" );  
  422.             }  
  423.   
  424.             return dt;  
  425.         }  
  426.         #endregion  
  427.     }  
  428.     #endregion  

 

抱歉!评论已关闭.