www.pudn.com > OracleServiceManager.zip > TimerObserver.cs


using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Runtime.CompilerServices; 
using System.ServiceProcess; 
using System.Threading; 
using System.Timers; 
using System.Windows.Forms; 
using kae.ServiceStatePublisher; 
 
namespace kae.OracleServiceManager 
{ 
	///  
	/// TimerObserver is a concrete observer listening to the current subject for changes. 
	/// TimerObserver uses a system timer to periodically check for changes made outside OSM. 
	///  
	public class TimerObserver 
	{ 
		private delegate void ChangeStateCallback( ServiceState state); 
 
		private System.Timers.Timer _timer; 
		private DateTime _stopTime; 
		private ServiceState _state; 
		private ISynchronizeInvoke _syncObject; 
		private ChangeStateCallback changeStateCallback; 
		private int _uiThreadId; 
 
		public TimerObserver( ServiceSubject subject, double interval) : this( subject, interval, null) 
		{ 
		} 
 
		public TimerObserver( ServiceSubject subject, double interval, ISynchronizeInvoke synchronizingObject) 
		{ 
			InitializeDebugInfo( "UIThread"); 
			Debug.WriteLine( String.Format( "UIThreadId = {0}", _uiThreadId)); 
 
			if (subject != null) 
			{ 
				subject.ServerChanged += new EventHandler( this.OnServerChanged); 
				subject.ServiceChanged += new EventHandler( this.OnServiceChanged); 
				subject.StateChanged += new EventHandler( this.OnStateChanged); 
			} 
 
			_timer = new System.Timers.Timer( interval); 
			_timer.Elapsed += new ElapsedEventHandler( this.OnTimerElapsed); 
			 
			SynchronizingObject = synchronizingObject; 
 
			changeStateCallback = new ChangeStateCallback( this.ChangeState); 
		} 
 
		public void Dispose() 
		{ 
			StopTimer(); 
			_timer.Dispose(); 
			_timer = null; 
		} 
 
		#region Debug Stuff 
		[Conditional("DEBUG")] 
		private void InitializeDebugInfo( string name) 
		{ 
			Thread.CurrentThread.Name = "UIThread"; 
			_uiThreadId = AppDomain.GetCurrentThreadId(); 
		} 
 
		[Conditional("DEBUG")] 
		private void WriteThreadDebugInfo( string methodName) 
		{ 
			string threadName = (AppDomain.GetCurrentThreadId() != _uiThreadId) ? "WorkerThread" : Thread.CurrentThread.Name; 
 
			Debug.WriteLine( String.Format( "{0}[{1}:{2}]", methodName, AppDomain.GetCurrentThreadId(), threadName)); 
		} 
		#endregion 
 
		internal ServiceState State 
		{ 
			get { return _state; } 
			set { _state = value; } 
		} 
 
		private ISynchronizeInvoke SynchronizingObject 
		{ 
			get { return _syncObject; } 
			set { _syncObject = value; } 
		} 
 
		public double Interval 
		{ 
			get { return _timer.Interval; } 
			set { _timer.Interval = value; } 
		} 
 
		internal DateTime StopTime 
		{ 
			get { return _stopTime; } 
			set { _stopTime = value; } 
		} 
 
		private void OnTimerElapsed( object sender, ElapsedEventArgs e) 
		{ 
			Debug.WriteLine( String.Format("OnTimerElapsed fired at {0}", e.SignalTime)); 
 
			if (e.SignalTime < StopTime) 
			{ 
				ServiceSubject subject = OracleServiceManager.Instance.Subject; 
				ServiceController service = new ServiceController( subject.Controller.ServiceName, subject.ServerName); 
				ServiceContext context = new ServiceContext( service); 
 
				WriteThreadDebugInfo( "OnTimerElapsed"); 
		 
				if (State.GetType() != context.State.GetType()) 
				{ 
					Debug.WriteLine( String.Format("State = {0}\ncontext.State = {1}", State.GetType(), context.State.GetType())); 
 
					object[] stateArray = new object[] { context.State }; 
					if (SynchronizingObject != null) 
						SynchronizingObject.BeginInvoke( changeStateCallback, stateArray); 
					else 
						ChangeState( context.State); 
				} 
			} 
		} 
 
		private void ChangeState( ServiceState state) 
		{ 
			WriteThreadDebugInfo( "ChangeState"); 
			 
			OracleServiceManager.Instance.Subject.State = state; 
		} 
 
		private void OnServerChanged( object sender, EventArgs e) 
		{ 
			ServiceSubject subject = (ServiceSubject) sender; 
			StopTimer(); 
			State = subject.State; 
		} 
 
		private void OnServiceChanged( object sender, EventArgs e) 
		{ 
			ServiceSubject subject = (ServiceSubject) sender; 
			State = subject.State; 
			StopTimer(); 
			if (subject.Controller != null) 
				StartTimer(); 
		} 
 
		private void OnStateChanged( object sender, EventArgs e) 
		{ 
			ServiceSubject subject = (ServiceSubject) sender; 
			State = subject.State; 
		} 
 
		private void StopTimer() 
		{ 
			StopTime = DateTime.Now; 
			_timer.Stop(); 
		} 
 
		private void StartTimer() 
		{ 
			StopTime = DateTime.MaxValue; 
			_timer.Start(); 
		} 
	} 
}