关于服务器定时器的封装

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

  1. testService.Start();  

原文地址:http://blog.csdn.net/Linux7985/article/details/5169375

0 0
原创粉丝点击