gpt4 book ai didi

C# 定时器和垃圾回收

转载 作者:太空狗 更新时间:2023-10-29 17:55:57 25 4
gpt4 key购买 nike

根据 MSDN ,应保留对 System.Threading.Timer 的引用,否则它将被垃圾回收。因此,如果我运行这段代码,它不会写入任何消息(这是预期的行为):

static void Main(string[] args)
{
RunTimer();
GC.Collect();
Console.ReadKey();
}

public static void RunTimer()
{
new Timer(s => Console.WriteLine("Hello"), null, TimeSpan.FromSeconds(1), TimeSpan.Zero);
}

但是,如果我通过将计时器存储在临时局部变量中来稍微修改代码,它会继续存在并写入消息:

public static void RunTimer()
{
var timer = new Timer(s => Console.WriteLine("Hello"));
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero);
}

在垃圾回收期间,显然没有办法从根对象或静态对象访问计时器。那么你能解释一下为什么计时器会存活下来吗?引用保存在哪里?

最佳答案

每个 Timer 引用一个 TimerHolder,后者引用一个 TimerQueueTimer。该实现通过调用 UpdateTimer() 保持对 TimerQueueTimer 的内部引用。 .

一般情况下你的定时器是可以免费领取的,finalizing the TimerHolder并从内部队列中删除 TimerQueueTimer。但是简单的构造函数 Timer(TimerCallback) calls TimerSetup()Timer 本身作为状态。因此,在这种特殊情况下,TimerQueueTimer 的状态引用回 Timer,阻止它被收集。

效果与保留临时局部变量无关。由于 Timer 机制的内部结构,它恰好可以工作。按照 MSDN 的建议保留对计时器的引用会更清晰、更安全。

关于C# 定时器和垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37681583/

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