gpt4 book ai didi

c# - 计时器委托(delegate)周围的内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 22:16:35 25 4
gpt4 key购买 nike

有时用户想要安排大量计时器,但不想管理对这些计时器的引用。
如果用户没有引用定时器,定时器可能会在执行前被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 集合中删除后,似乎有人持有对计时器委托(delegate)的引用。

问题是,如果我不处理计时器,为什么会发生内存泄漏?

最佳答案

Timer 由计时器本身创建的 GCHandle 保持事件状态。这可以使用 .net 内存分析器进行测试。反过来,Timer 将使委托(delegate)保持事件状态,然后委托(delegate)保持事件状态。

GCHandle 是一种特殊的对象,可用于“欺骗”垃圾收集器,使无法访问的对象保持事件状态。

你实际上可以在没有分析器的情况下使用以下方法测试它:

var a = new ClassA();
var timer = new Timer(a.Exec);

var refA = new WeakReference(a);
var refTimer = new WeakReference(timer);

a = null;
timer = null;

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Console.WriteLine(refA.IsAlive);
Console.WriteLine(refTimer.IsAlive);

关于c# - 计时器委托(delegate)周围的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13205024/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com