`
vrzd62vrzd
  • 浏览: 10838 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

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; } ///  /// 当服务出错时,处理 ///  ///  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 { ///  /// 服务定时器管理 ///  public abstract class ServiceTimerControl { #region 私有成员 ///  /// 定时器 ///  private Timer SysTimer { get; set; } ///  /// 是否启用定时器 ///  private bool _EnabledTimer = true; ///  /// 服务执行状态 ///  private ServiceStatus _serviceStatus = ServiceStatus.Sleep; ///  /// 时间计算类 ///  private TimerControl _timerControl = null; ///  /// 定时器配置 ///  ServiceTimeConfig Config; #endregion #region 公共属性 ///  /// 获取服务状态 ///  public ServiceStatus ServiceStatus { get { return _serviceStatus; } } ///  /// 计时模式 ///  public TimerMode TimerMode { get { if ( Config == null ) Config = this.GetTimerConfig(); return Config.TimerMode; } } ///  /// 计时配置 ///  public string StartTime { get { return ( Config == null ) ? "" : Config.StartTime; } } ///  /// 时间计算类 ///  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 ///  /// 停止 ///  public void Stop() { _EnabledTimer = false; SysTimer.Change( Timeout.Infinite, Timeout.Infinite ); } ///  /// 开始服务 ///  public void Start() { _EnabledTimer = true; Config = this.GetTimerConfig(); SysTimer = new Timer( new TimerCallback( this.TimerProcess ), AppDomain.CurrentDomain, 0, this.Config.ChkInterval ); } ///  /// 处理间隔服务 ///  ///  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; } } ///  /// 开始服务 ///  protected abstract void StartService(); ///  /// 定时器初始化 ///  ///  ///  ///  protected abstract ServiceTimeConfig GetTimerConfig(); ///  /// 系统服务错误 ///  ///  protected virtual void ServiceException( Exception ex ) { return; } } #region 定时器相关实体类 ///  /// 服务定时器配置 ///  public class ServiceTimeConfig { ///  /// 轮询目录时间间隔(单位:毫秒) ///  public int ChkInterval { get; set; } ///  /// 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) ///  public string StartTime { get; set; } ///  /// 服务器定时处理模型 ///  public TimerMode TimerMode { get; set; } } ///  /// 服务处理方法 ///  public enum TimerMode { ///  /// 轮询方式 ///  Interval = 0, ///  /// 一个月中某个天数的指定时间 ///  Month = 1, ///  /// 一周中的周几的指定时间 ///  Week = 2, ///  /// 一天中的指定时间 ///  Day = 3, ///  /// 一年中第几天的指定时间 ///  Year = 4, ///  /// 一年中的指定日期的指定时间 ///  Date = 5, ///  /// 未设置 ///  NoSet } ///  /// 服务处理方法 ///  public enum ServiceStatus { ///  /// 休眠中 ///  Sleep = 0, ///  /// 服务在执行过程中 ///  Running = 1 } #endregion #region 定时服务休眠时间计算类 ///  /// 定时服务休眠时间计算类 ///  public class TimerControl { #region 私有成员 ///  /// 间隔单位 ///  private TimerMode type; ///  /// 月份 ///  private int Month; ///  /// 天 ///  private int Day; ///  /// 小时 ///  private int Hour; ///  /// 分钟 ///  private int Minute = 0; #endregion #region 公共成员方法 ///  /// 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) ///  ///  ///  public TimerControl( string StartTime, TimerMode timeMode ) { //Regex regEx = new Regex( @"(?[MWDY])(?\d+)?\|(?\d+):?(?[0 -5]\d?)?", RegexOptions.Compiled | RegexOptions.IgnoreCase ); Regex regEx = new Regex( @"^(?:(?[0]?\d|1[0-2])-)?(?\d{1,3})?\|(?[01]?\d|2[0-3])(?::(?[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( "定时器时间配置异常!" ); } ///  /// 判断时间是否到了 ///  ///  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; } } ///  /// 从现在起到下次时间到还有多少时间 ///  ///  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; } ///  /// 获取下一次指定配置的时间是多少 ///  ///  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 } 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics