TKK_E32230371/UPSNet/BackgroudTimer.cs

108 lines
2.5 KiB
C#

//example of use:
//// In your UPS monitoring class
//private readonly BackgroundTimer _monitoringTimer;
//
//public UPSMonitor()
//{
// _monitoringTimer = new BackgroundTimer(CheckUPSStatus, 1000);
//}
//
//private void CheckUPSStatus()
//{
// var charge = GetBatteryCharge();
// if (charge < 10) EmergencyShutdown();
//}
using System;
using System.Threading;
namespace UPSNet
{
public class BackgroundTimer : IDisposable
{
private readonly Timer _timer;
private readonly Action _callback;
private readonly int _intervalMs;
private volatile bool _isRunning;
private readonly object _lock = new object();
public BackgroundTimer(Action callback, int intervalMs, bool startImmediately = true)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
_callback = callback;
_intervalMs = intervalMs;
_timer = new Timer(TimerCallback, null, Timeout.Infinite, Timeout.Infinite);
if (startImmediately)
{
Start();
}
}
public void Start()
{
lock (_lock)
{
if (!_isRunning)
{
_isRunning = true;
_timer.Change(0, _intervalMs);
}
}
}
public void Stop()
{
lock (_lock)
{
if (_isRunning)
{
_isRunning = false;
_timer.Change(Timeout.Infinite, Timeout.Infinite);
}
}
}
private void TimerCallback(object state)
{
if (!_isRunning || !Monitor.TryEnter(_lock))
return;
try
{
if (_isRunning)
{
_callback.Invoke();
}
}
catch
{
// Suppress errors to prevent thread crashes
}
finally
{
Monitor.Exit(_lock);
}
}
public void Dispose()
{
Stop();
_timer.Dispose();
}
public void Restart(int newIntervalMs)
{
lock (_lock)
{
Stop();
_timer.Change(newIntervalMs, newIntervalMs);
_isRunning = true;
}
}
}
}