I used this code in several projects. But I am not sure if it is stable. However on production it is working well, but I want to listen your advices:
/// <summary>
/// Standard abstract parent for Timer-powered classes. Has Start|Stop|Pulse events
/// </summary>
public abstract class TimerContainer : IDisposable
{
protected Timer Timer { get; set; }
protected TimeSpan Interval { get; set; }
protected TimerContainer() : this(TimeSpan.FromSeconds(1)) { }
protected TimerContainer(TimeSpan interval)
{
Status = TimerStatus.NotInitialized;
Timer = new Timer(OnTick, null, Timeout.Infinite, Timeout.Infinite);
Interval = interval;
}
protected abstract void OnTick(object sender);
#region Standard Events
public event EventHandler OnStart;
public event EventHandler OnStop;
public event EventHandler OnPulse;
public TimerStatus Status { get; protected set; }
public void Start()
{
Timer.Change(TimeSpan.Zero, Interval);
Status = TimerStatus.Running;
if (OnStart != null) {
OnStart(this, new EventArgs());
}
}
public void Stop()
{
Status = TimerStatus.Stopped;
Timer.Change(Timeout.Infinite, Timeout.Infinite);
if (OnStop != null) {
OnStop(this, new EventArgs());
}
}
protected void InvokePulse()
{
if (OnPulse != null) {
OnPulse(this, new EventArgs());
}
}
#region IDisposable Members
protected bool disposed = false;
~TimerContainer()
{
Dispose(false);
}
public virtual void Dispose()
{
if (!disposed) {
Dispose(true);
GC.SuppressFinalize(this);
disposed = true;
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing) {
if (Status != TimerStatus.Stopped) {
Stop();
}
if (Timer != null) {
Timer.Dispose();
Timer = null;
}
}
}
#endregion
#endregion
}
/// <summary>
/// Timer status
/// </summary>
public enum TimerStatus
{
NotInitialized = 0,
Running = 1,
Stopped = 2
}