gpt4 book ai didi

c# - 定时器可以自动收集垃圾吗?

转载 作者:IT王子 更新时间:2023-10-29 04:26:20 27 4
gpt4 key购买 nike

当您使用将在程序的整个生命周期内运行的TimerThread 时,您是否需要保留对它们的引用以防止它们被收集垃圾?

请撇开下面的程序可以将 timer 作为类中的静态变量这一事实,这只是一个演示问题的玩具示例。

public class Program
{
static void Main(string[] args)
{
CreateTimer();

Console.ReadLine();
}

private static void CreateTimer()
{
var program = new Program();

var timer = new Timer();
timer.Elapsed += program.TimerElapsed;
timer.Interval = 30000;
timer.AutoReset = false;
timer.Enabled = true;
}

private void TimerElapsed(object sender, ElapsedEventArgs e)
{
var timerCast = (Timer)sender;

Console.WriteLine("Timer fired at in thread {0}", GetCurrentThreadId());

timerCast.Enabled = true;
}

~Program()
{
Console.WriteLine("Program Finalized");
}

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
}

可以在上面的示例中收集计时器吗?我运行了一段时间,没有出现异常,也没有消息说 ~Program() 被调用了。

更新:我从 this question 中发现( thanks sethcran ) 线程由 CLR 跟踪,但我仍然想要有关计时器的答案。

最佳答案

这只是 System.Threading.Timer 类的一个问题,如果您不以其他方式在某处存储对它的引用的话。它有几个构造函数重载,采用state 对象的那些很重要。 CLR 关注那个状态对象。只要它在某处被引用,CLR 就会将计时器保留在其计时器队列中,并且计时器对象不会被垃圾回收。大多数程序员不会使用那个状态对象,MSDN 文章当然没有解释它的作用。

System.Timers.Timer 是 System.Threading.Timer 类的包装器,使其更易于使用。特别是,只要启用计时器,它将使用该状态对象并保留对它的引用。

请注意,在您的情况下,计时器的 Enabled 属性在进入您的 Elapsed 事件处理程序时为 false,因为您设置了 AutoReset = false。因此,计时器一进入您的事件处理程序就符合收集条件。但是您可以通过引用 sender 参数来避免麻烦,该参数需要将 Enabled 设置回 true。这使得抖动报告成为引用,因此您没有问题。

请务必小心 Elapsed 事件处理程序。该方法内抛出的任何异常都将在没有诊断的情况下被吞噬。这也意味着您不会将 Enabled 设置回 true。您必须使用 try/catch 来做一些合理的事情。如果你不打算有意结束你的程序,至少你需要让你的主程序知道某些东西不再工作了。将 Enabled = true 放在 finally 子句中可以避免收集计时器垃圾,但有让您的程序一遍又一遍地抛出异常的风险。

关于c# - 定时器可以自动收集垃圾吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18136735/

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