首页 > 代码库 > C#开发系统服务时用的定时器组件

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

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

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

 

下面是应用实例

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

using System;   using System.Collections.Generic;   using System.IO;   using System.Text.RegularExpressions;   using System.Threading;  namespace BlueVision.SaYuan.WinService   {       public class TestService : ServiceTimerContorl       {           protected override void StartService()           {               //需要做的事情的代码           }             protected override ServiceTimeConfig GetTimerConfig()           {               ServiceTimeConfig config = new ServiceTimeConfig();                 // 如果该枚举是选择 Interval ,则表示,上述的 StartService 方法,将隔 config.ChkInterval 毫秒执行一次               config.TimerMode = TimerMode.Interval;               config.ChkInterval = 100000;                   /// StartTime值为:               ///                /// TimerMode=TimerMode.Month   "09|04:30"  -表示每月9号的凌晨4点30分               /// TimerMode=TimerMode.Week     "0|04:30"  -表示每星期天的4点30分               /// TimerMode=TimerMode.Week     "6|04:00"  -表示每星期6的4点30分               /// TimerMode=TimerMode.Day       "|04:00"  -表示每天的4点00分               /// TimerMode=TimerMode.Date "08-10|04:00"  -表示每年8月10号的4点00分执行一次               /// TimerMode=TimerMode.Year   "246|04"     -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)                 //如果是这样设置 则表示,每天的凌晨 4 点 00 执行一次               config.TimerMode = TimerMode.Day;               config.StartTime = "|04";                 //如果是这样设置 则表示,每个星期的星期四那天的凌晨 6 点 35 执行一次               config.TimerMode = TimerMode.Week;               config.StartTime = "4|06:35";                 //如果是这样设置 则表示,每个星期的星期天那天的凌晨 6 点 00 执行一次               config.TimerMode = TimerMode.Week;               config.StartTime = "0|06";                 //如果是这样设置 则表示,每个月的9号凌晨 6 点 28 执行一次               config.TimerMode = TimerMode.Month;               config.StartTime = "09|06:28";                 //如果是这样设置 则表示,每年8月10号的4点00分执行一次               config.TimerMode = TimerMode.Date;               config.StartTime = "08-10|04:00";                 //如果是这样设置 则表示,每年第246天的4点27分执行一次               config.TimerMode = TimerMode.Year;               config.StartTime = "246|04:27";                 return config;           }           /// <summary>           /// 当服务出错时,处理           /// </summary>           /// <param name="ex"></param>           protected override void  ServiceException(Exception ex)           {                //可以不实现           }       }   }       //要执行代码,以下这样就可以了TestService testService = new TestService();   testService.Start(); 

以下是组件的源代码

using System;using System.Collections.Generic;using System.IO;using System.Text.RegularExpressions;using System.Threading;namespace BlueVision.SaYuan.WinService{    /// <summary>    /// 服务定时器管理    /// </summary>    public abstract class ServiceTimerControl    {        #region 私有成员        /// <summary>        /// 定时器        /// </summary>        private Timer SysTimer { get; set; }        /// <summary>        /// 是否启用定时器        /// </summary>        private bool _EnabledTimer = true;        /// <summary>        /// 服务执行状态        /// </summary>        private ServiceStatus _serviceStatus = ServiceStatus.Sleep;        /// <summary>        /// 时间计算类        /// </summary>        private TimerControl _timerControl = null;        /// <summary>        /// 定时器配置        /// </summary>        ServiceTimeConfig Config;        #endregion        #region 公共属性        /// <summary>        /// 获取服务状态        /// </summary>        public ServiceStatus ServiceStatus { get { return _serviceStatus; } }        /// <summary>        /// 计时模式        /// </summary>        public TimerMode TimerMode        {            get            {                if ( Config == null ) Config = this.GetTimerConfig();                return Config.TimerMode;            }        }        /// <summary>        /// 计时配置        /// </summary>        public string StartTime { get { return ( Config == null ) ? "" : Config.StartTime; } }        /// <summary>        /// 时间计算类        /// </summary>        public TimerControl TimerControl        {            get            {                if ( Config == null )                    Config = this.GetTimerConfig();                if ( _timerControl == null )                    _timerControl = new TimerControl( this.Config.StartTime, this.Config.TimerMode );                return _timerControl;            }        }        #endregion        /// <summary>        /// 停止        /// </summary>        public void Stop()        {            _EnabledTimer = false;            SysTimer.Change( Timeout.Infinite, Timeout.Infinite );        }        /// <summary>        /// 开始服务        /// </summary>        public void Start()        {            _EnabledTimer = true;            Config = this.GetTimerConfig();            SysTimer = new Timer( new TimerCallback( this.TimerProcess ), AppDomain.CurrentDomain, 0, this.Config.ChkInterval );        }        /// <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                {                    _timerControl = new TimerControl( this.Config.StartTime, this.Config.TimerMode );                    TimeIsUp = _timerControl.TimeIsUp;    // 获取是否到了执行服务程序的时间了                }                catch ( Exception ex )                {                    // 读取配置出错且TimerControl对象已不存在,则再抛出异常                    // 如果上一次读取配置成功,那就就算这次的配置有问题,则也不会停止程序的运行,仍用上一次的数据做为参数                    if ( _timerControl == null ) throw ex;                }            }            try            {                if ( TimeIsUp )// 时间到了可以执行程序了                {                    // 服务运行了                    _serviceStatus = ServiceStatus.Running;                    // 设置计时器,在无穷时间后再启用(实际上就是永远不启动计时器了--停止计时器计时)                    SysTimer.Change( Timeout.Infinite, this.Config.ChkInterval );                    //开始处理服务                    this.StartService();                }            }            catch ( Exception ex ) { this.ServiceException( ex ); }    // 处理服务执行过程中出现的异常            finally            {                // 如果计时器不为空,则重新设置休眠的时间                if ( SysTimer != null )                {                    if ( this.Config.TimerMode == TimerMode.Interval )// 定时轮询设置                    {                        // 重新启用计时器                        SysTimer.Change( this.Config.ChkInterval, this.Config.ChkInterval );                    }                    else// 定时设置                    {                        // 用cft类计算下一次到期的时间                        TimeSpan Interval = _timerControl.GetNextTimeUp();                        // 重新启用计时器                        SysTimer.Change( Interval, Interval );                    }                }                _serviceStatus = ServiceStatus.Sleep;            }        }        /// <summary>        /// 开始服务        /// </summary>        protected abstract void StartService();        /// <summary>        /// 定时器初始化        /// </summary>        /// <param name="TimerMode"></param>        /// <param name="StartTime"></param>        /// <param name="ChkInterval"></param>        protected abstract ServiceTimeConfig GetTimerConfig();        /// <summary>        /// 系统服务错误        /// </summary>        /// <param name="ex"></param>        protected virtual void ServiceException( Exception ex ) { return; }    }    #region 定时器相关实体类    /// <summary>    /// 服务定时器配置    /// </summary>    public class ServiceTimeConfig    {        /// <summary>        /// 轮询目录时间间隔(单位:毫秒)        /// </summary>        public int ChkInterval { get; set; }        /// <summary>        /// StartTime值为:        ///         /// TimerMode=TimerMode.Month    "09|04:30"    -表示每月9号的凌晨4点30分        ///    TimerMode=TimerMode.Week     "0|04:30"    -表示每星期天的4点30分        /// TimerMode=TimerMode.Week     "6|04:00"    -表示每星期6的4点30分        ///    TimerMode=TimerMode.Day          "|04:00"    -表示每天的4点00分        ///    TimerMode=TimerMode.Date "08-10|04:00"    -表示每年8月10号的4点00分执行一次        ///    TimerMode=TimerMode.Year   "246|04"        -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)        /// </summary>        public string StartTime { get; set; }        /// <summary>        /// 服务器定时处理模型        /// </summary>        public TimerMode TimerMode { 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>        /// 未设置        /// </summary>        NoSet    }    /// <summary>    /// 服务处理方法    /// </summary>    public enum ServiceStatus    {        /// <summary>        /// 休眠中        /// </summary>        Sleep = 0,        /// <summary>        /// 服务在执行过程中        /// </summary>        Running = 1    }    #endregion    #region 定时服务休眠时间计算类    /// <summary>    /// 定时服务休眠时间计算类    /// </summary>    public class TimerControl    {        #region 私有成员        /// <summary>        /// 间隔单位        /// </summary>        private TimerMode type;        /// <summary>        /// 月份        /// </summary>        private int Month;        /// <summary>        ////// </summary>        private int Day;        /// <summary>        /// 小时        /// </summary>        private int Hour;        /// <summary>        /// 分钟        /// </summary>        private int Minute = 0;        #endregion        #region 公共成员方法        /// <summary>        /// StartTime值为:        ///         /// TimerMode=TimerMode.Month    "09|04:30"    -表示每月9号的凌晨4点30分        ///    TimerMode=TimerMode.Week     "0|04:30"    -表示每星期天的4点30分        /// TimerMode=TimerMode.Week     "6|04:00"    -表示每星期6的4点30分        ///    TimerMode=TimerMode.Day          "|04:00"    -表示每天的4点00分        ///    TimerMode=TimerMode.Date "08-10|04:00"    -表示每年8月10号的4点00分执行一次        ///    TimerMode=TimerMode.Year   "246|04"        -表示每年第246天的4点00分执行一次(可以不填写分钟默认为00)        /// </summary>        /// <param name="StartTime"></param>        /// <param name="timeMode"></param>        public TimerControl( string StartTime, TimerMode timeMode )        {            //Regex regEx = new Regex( @"(?<Type>[MWDY])(?<Days>/d+)?/|(?<Hour>/d+):?(?<Minute>[0-5]/d?)?", RegexOptions.Compiled | RegexOptions.IgnoreCase );            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 );            this.type = timeMode;            Match m = regEx.Match( StartTime );            if ( m.Success )            {                if ( String.IsNullOrEmpty( m.Groups["Month"].Value ) && this.type == TimerMode.Date )                    throw new Exception( "定时器时间配置异常!" );                if ( !String.IsNullOrEmpty( m.Groups["Month"].Value ) )                    this.Month = Convert.ToInt32( m.Groups["Month"].Value );                if ( !String.IsNullOrEmpty( m.Groups["Days"].Value ) )                    this.Day = Convert.ToInt32( m.Groups["Days"].Value );                this.Hour = Convert.ToInt32( m.Groups["Hour"].Value );                if ( !String.IsNullOrEmpty( m.Groups["Minute"].Value ) )                    this.Minute = Convert.ToInt32( m.Groups["Minute"].Value );            }            else                throw new Exception( "定时器时间配置异常!" );        }        /// <summary>        /// 判断时间是否到了        /// </summary>        /// <returns></returns>        public bool TimeIsUp        {            get            {                DateTime dt = DateTime.Now;                switch ( type )                {                    case TimerMode.Day:                        return ( dt.Hour == this.Hour && dt.Minute == this.Minute );                    case TimerMode.Month:                        return ( dt.Day == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );                    case TimerMode.Week:                        return ( ( ( int )dt.DayOfWeek ) == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );                    case TimerMode.Date:                        return ( dt.Month == this.Month && dt.Day == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );                    case TimerMode.Year:                        return ( dt.DayOfYear == this.Day && dt.Hour == this.Hour && dt.Minute == this.Minute );                }                return false;            }        }        /// <summary>        /// 从现在起到下次时间到还有多少时间        /// </summary>        /// <returns></returns>        public TimeSpan GetNextTimeUp()        {            ///目标时间            DateTime _NextDateTime = this.GetNextDateTime();    // 保存下一次要执行的时间            TimeSpan NextCrtFileTime = _NextDateTime - DateTime.Now;            if ( ( int )NextCrtFileTime.TotalMilliseconds > int.MaxValue )    // 如果要休眠的时间间隔超过int类型可以表示的毫秒时,先休眠到int.MaxValue,然后再次休眠                NextCrtFileTime = new TimeSpan( int.MaxValue );            return NextCrtFileTime;        }        /// <summary>        /// 获取下一次指定配置的时间是多少        /// </summary>        /// <returns></returns>        public DateTime GetNextDateTime()        {            DateTime dt = DateTime.Now;            DateTime now, target;            switch ( this.type )            {                case TimerMode.Day:                    #region 每天指定某时执行一次                    now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, 0 );                    target = new DateTime( 1, 1, 1, this.Hour, this.Minute, 0 );                    if ( now.Ticks >= target.Ticks ) dt = dt.AddDays( 1.0 );    //如果当前时间小于指定时刻,则不需要加天                    dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );                    #endregion                    break;                case TimerMode.Month:                    #region 每月指定某天某时执行一次                    now = new DateTime( 1, 1, dt.Day, dt.Hour, dt.Minute, 0 );                    target = new DateTime( 1, 1, this.Day, this.Hour, this.Minute, 0 );                    if ( now.Ticks >= target.Ticks ) dt = dt.AddMonths( 1 );                    dt = new DateTime( dt.Year, dt.Month, this.Day, this.Hour, this.Minute, 0 );                    #endregion                    break;                case TimerMode.Week:                    #region 每星期指定星期某时执行一次                    int dow = ( int )dt.DayOfWeek;                    now = new DateTime( 1, 1, dow + 1, dt.Hour, dt.Minute, 0 );                    target = new DateTime( 1, 1, this.Day + 1, this.Hour, this.Minute, 0 );                    if ( now.Ticks >= target.Ticks )                        dt = dt.AddDays( this.Day - dow + 7 );                    else                        dt = dt.AddDays( this.Day - dow );                    dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );                    #endregion                    break;                case TimerMode.Date:                    #region 每年指定某月某日某时执行一次                    now = new DateTime( 1, dt.Month, dt.Day, dt.Hour, dt.Minute, 0 );                    target = new DateTime( 1, this.Month, this.Day, this.Hour, this.Minute, 0 );                    if ( now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 );                    dt = new DateTime( dt.Year, this.Month, this.Day, this.Hour, this.Minute, 0 );                    #endregion                    break;                case TimerMode.Year:                    #region 每年指定第N天某时执行一次                    now = new DateTime( 1, 1, 1, dt.Hour, dt.Minute, 0 );                    target = new DateTime( 1, 1, 1, this.Hour, this.Minute, 0 );                    if ( dt.DayOfYear > this.Day || dt.DayOfYear == this.Day && now.Ticks >= target.Ticks ) dt = dt.AddYears( 1 );                    dt = dt.AddDays( this.Day - dt.DayOfYear );                    dt = new DateTime( dt.Year, dt.Month, dt.Day, this.Hour, this.Minute, 0 );                    #endregion                    break;                default:                    throw new Exception( "定时器时间配置异常!" );            }            return dt;        }        #endregion    }    #endregion}

 

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