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