有时用户想要安排大量的计时器,并且不想管理对这些计时器的引用。
如果用户不引用计时器,则计时器可能会在执行之前由 GC 收集。
我创建了 Timers 类作为新创建的计时器的占位符:
static class Timers
{
private static readonly ILog _logger = LogManager.GetLogger(typeof(Timers));
private static readonly ConcurrentDictionary<Object, Timer> _timers = new ConcurrentDictionary<Object, Timer>();
/// <summary>
/// Use this class in case you want someone to hold a reference to the timer.
/// Timer without someone referencing it will be collected by the GC even before execution.
/// </summary>
/// <param name="dueTime"></param>
/// <param name="action"></param>
internal static void ScheduleOnce(TimeSpan dueTime, Action action)
{
if (dueTime <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("dueTime", dueTime, "DueTime can only be greater than zero.");
}
Object obj = new Object();
Timer timer = new Timer(state =>
{
try
{
action();
}
catch (Exception ex)
{
_logger.ErrorFormat("Exception while executing timer. ex: {0}", ex);
}
finally
{
Timer removedTimer;
if (!_timers.TryRemove(obj, out removedTimer))
{
_logger.Error("Failed to remove timer from timers");
}
else
{
removedTimer.Dispose();
}
}
});
if (!_timers.TryAdd(obj, timer))
{
_logger.Error("Failed to add timer to timers");
}
timer.Change(dueTime, TimeSpan.FromMilliseconds(-1));
}
}
如果我不处理已删除的计时器,则会导致内存泄漏。
从集合
中删除计时器后,似乎有人持有对计时器委托的引用。_timers
问题是,如果我不处置计时器,为什么会出现内存泄漏?