I am currently refactoring a larger solution where the compiler gave multiple warnings about disposing the used System.Timers.Timer
instances. The timers are running in short intervals so I would have to check before I dispose the timer if the elapsed callback is currently active.
Following the implementation with which I want to replace the System.Timers.Timer
instances.
public class DisposableSafeTimer : IDisposable
{
public event ElapsedEventHandler Elapsed;
private System.Timers.Timer _timer;
private readonly object _syncObject = new object();
private volatile bool _isDisposing = false;
public double Interval
{
get { return _timer.Interval; }
set { _timer.Interval = value; }
}
public DisposableSafeTimer()
{
_timer = new System.Timers.Timer();
_timer.Elapsed += _timer_Elapsed;
}
public void ExternalStart()
{
_timer.Start();
}
public void ExternalStop()
{
_timer.Stop();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
lock (_syncObject)
{
if(_isDisposing)
{
return;
}
if (disposing)
{
_isDisposing = disposing;
_timer.Stop();
_timer.Elapsed -= _timer_Elapsed;
_timer.Dispose();
}
}
}
private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (_syncObject)
{
if (_isDisposing)
{
return;
}
try
{
_timer.Stop();
Elapsed?.Invoke(sender, e);
}
finally
{
_timer.Start();
}
}
}
}
The Methods ExternalStart()
and ExternalStop()
are named with the intention that I get compiler errors wherever the Timer.Start()
and Timer.Stop()
methods are called. The stops and starts from the classes which use my timer implementation shouldn't care about the cyclic starts and stops of the internal timer.
So far I had no problems with my tests. I just want to make sure that I haven't overlooked something. Suggestions for improvements are welcome.