using System; using System.Threading; namespace Chernobyl.Timing { /// /// Decorates a with only a to the callback so /// that the timer does not prevent GC from collecting the object that uses this timer. Your /// object must hold a reference to the callback passed into this timer. If the callback is /// garbage collected, then the timer is disposed. /// public class WeakTimer : IDisposable { // This code is a modified version of the code found here: https://stackoverflow.com/a/44253691. /// /// Performs the same action as . /// public WeakTimer(TimerCallback callback) { _timer = new Timer(OnTimerCallback); _weakCallback = new WeakReference(callback); } /// /// Performs the same action as . /// public WeakTimer(TimerCallback callback, object state, int dueTime, int period) { _timer = new Timer(OnTimerCallback, state, dueTime, period); _weakCallback = new WeakReference(callback); } /// /// Performs the same action as . /// public WeakTimer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period) { _timer = new Timer(OnTimerCallback, state, dueTime, period); _weakCallback = new WeakReference(callback); } /// /// Performs the same action as . /// public WeakTimer(TimerCallback callback, object state, uint dueTime, uint period) { _timer = new Timer(OnTimerCallback, state, dueTime, period); _weakCallback = new WeakReference(callback); } /// /// Performs the same action as . /// public WeakTimer(TimerCallback callback, object state, long dueTime, long period) { _timer = new Timer(OnTimerCallback, state, dueTime, period); _weakCallback = new WeakReference(callback); } /// /// Performs the same action as . /// public bool Change(int dueTime, int period) { return _timer.Change(dueTime, period); } /// /// Performs the same action as . /// public bool Change(TimeSpan dueTime, TimeSpan period) { return _timer.Change(dueTime, period); } /// /// Performs the same action as . /// public bool Change(uint dueTime, uint period) { return _timer.Change(dueTime, period); } /// /// Performs the same action as . /// public bool Change(long dueTime, long period) { return _timer.Change(dueTime, period); } /// /// Performs the same action as . /// public bool Dispose(WaitHandle notifyObject) { return _timer.Dispose(notifyObject); } /// public void Dispose() { _timer.Dispose(); } // Invokes the weakly referenced callback if it exists, disposes of the timer if it doesn't. void OnTimerCallback(object state) { TimerCallback callback = _weakCallback.Target; if (callback != null) callback(state); else _timer.Dispose(); } // The time being decorated. readonly Timer _timer; // The callback to invoke. readonly WeakReference _weakCallback; } }