【发布时间】:2012-11-03 01:08:37
【问题描述】:
有时用户想要安排大量计时器,但不想管理对这些计时器的引用。
如果用户没有引用定时器,定时器可能会在执行之前被 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 集合中删除后,似乎有人持有对计时器委托的引用。
问题是,如果我不处置计时器,为什么会出现内存泄漏?
【问题讨论】:
-
也许我不明白你在问什么,因为听起来你想知道为什么当你虐待它时会出现行为不端......
-
我了解文档中说组件应该被处理掉。我仍然很好奇是什么阻止了 GC 在不调用 dispose 方法的情况下收集计时器和给定的委托。
标签: c# .net multithreading timer