//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; } } } }