- using System;
- using System.Text;
- using System.Windows.Forms;
- using UpSoft.Framework.CommonFunction.WinService;
-
- namespace TestProject
- {
-
-
-
- public class TestServices : ServiceTimerControl
- {
-
-
-
- protected override void StartService()
- {
-
- }
-
-
-
-
- public override string ConfigName { get { return "A"; } }
- }
- }
-
-
- 要调用时,只需输入以下代码
- new TestServices().Start();
-
-
-
-
- protected override TimerConfig GetTimerConfig()
- {
- return new TimerConfig{ TimerMode=..., ...};
- }
以下是组件的源代码
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- using System.Text.RegularExpressions;
- using System.Threading;
- using System.Xml;
-
- namespace UpSoft.Framework.CommonFunction.WinService
- {
-
-
-
- public abstract class ServiceTimerControl
- {
- #region 私有成员
-
-
-
- private Timer SysTimer { get; set; }
-
-
-
- private bool _EnabledTimer = true;
-
-
-
- private int _serviceStatus = 0;
- #endregion
-
- #region 公共属性
-
-
-
- public int ServiceStatus { get { return _serviceStatus; } }
-
-
-
-
- public TimerConfig Config { get; set; }
-
-
-
-
- public TimerControl TimerControl { get; set; }
-
-
-
-
- public virtual string ConfigName { get { return ( ServiceTimerConfigManager.ServiceConfig == null ? "" : ServiceTimerConfigManager.ServiceConfig.Default ); } }
- #endregion
-
-
-
-
- public void Stop()
- {
- _EnabledTimer = false;
-
- if ( SysTimer != null ) SysTimer.Change( Timeout.Infinite, Timeout.Infinite );
- }
-
-
-
-
- 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 );
- }
- }
-
-
-
-
- public void Process()
- {
- try
- {
-
- this.StartService();
- }
- catch ( Exception ex ) { this.ServiceException( ex ); }
- }
-
-
-
-
-
- private void TimerProcess( object sender )
- {
- if ( !_EnabledTimer ) return;
-
- bool TimeIsUp = true;
- if ( this.Config.TimerMode != TimerMode.Interval )
- {
-
-
- try
- {
- this.TimerControl = new TimerControl( this.Config );
- TimeIsUp = this.TimerControl.TimeIsUp;
- }
- catch ( Exception ex )
- {
-
-
- 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
- {
-
- TimeSpan Interval = this.TimerControl.GetNextTimeUp();
-
- SysTimer.Change( Interval, Interval );
- }
- }
- _serviceStatus = 0;
- }
- }
-
-
-
-
- protected abstract void StartService();
-
-
-
-
-
-
- protected virtual void Logger( LogLevel level, string msg ) { return; }
-
-
-
-
- protected virtual TimerConfig GetTimerConfig()
- {
- var config = ServiceTimerConfigManager.ServiceConfig;
- if ( config != null && config.Config.Length > 0 )
- {
-
- 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( "时间策略配置不正确!" );
- }
-
-
-
-
-
- protected virtual void ServiceException( Exception ex ) { this.Logger( LogLevel.ERROR, "服务异常:" + ex.Message + " \r\n堆栈:" + ex.StackTrace ); }
- }
-
- #region 定时服务休眠计算类
-
-
-
- public class TimerControl
- {
- #region 私有成员
- private TimerConfig Config { get; set; }
- #endregion
-
- #region 公共成员方法
-
-
-
-
-
- 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 );
- 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 )
- {
- 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;
- }
- }
-
-
-
-
-
- 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;
- }
- }
-
-
-
-
-
- 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;
- }
- }
-
-
-
-
-
- public TimeSpan GetNextTimeUp()
- {
-
- DateTime _NextDateTime = this.GetNextDateTime();
- return _NextDateTime - DateTime.Now;
- }
-
-
-
-
-
- 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 );
- if ( now.Ticks >= target.Ticks ) dt = dt.AddMonths( 1 );
-
-
-
-
-
-
-
- if ( Config.DaySeq > GetLastDayByMonth( dt ) ) dt = dt.AddMonths( 1 );
-
- 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 );
- 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 );
-
-
-
- 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 )
- {
-
- 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;
- }
-
-
-
-
-
-
- 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;
- }
- }
-
-
-
-
-
- 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 系统配置实体类&配置读取类
-
-
-
- public class ServiceTimerConfig
- {
-
-
-
- public string Default { get; set; }
-
-
-
- public TimerConfig[] Config { get; set; }
- }
-
-
-
- public class TimerConfig
- {
-
-
-
- public string RefName { get; set; }
-
-
-
-
-
- public TimerMode TimerMode { get; set; }
-
-
-
-
-
-
-
-
-
-
- public int DaySeq { get; set; }
-
-
-
-
- public int MonthSeq { get; set; }
-
-
-
-
- public TimeSpan Interval { get; set; }
-
-
-
-
- public TimeSpan Delay { get; set; }
-
-
-
-
- public TimeSpan[] Times { get; set; }
- }
-
-
-
- public enum TimerMode
- {
-
-
-
- Interval = 0,
-
-
-
- Month = 1,
-
-
-
- Week = 2,
-
-
-
- Day = 3,
-
-
-
- Year = 4,
-
-
-
- Date = 5,
-
-
-
- LastDayOfMonth,
-
-
-
- NoSet
- }
-
-
-
- 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 );
-
-
-
-
- public static ServiceTimerConfig ServiceConfig { get; set; }
-
-
-
- static ServiceTimerConfigManager()
- {
- ConfigurationManager.GetSection( "ServiceTimerConfig" );
- }
-
-
-
-
-
-
-
- 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;
- }
-
-
-
-
-
- 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 );
- break;
- case "interval":
- Int64.TryParse( xn.InnerText, out longTmp );
- 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
- }
C#开发系统服务时用的定时器组件
原文:http://www.cnblogs.com/gc2013/p/3940774.html