可能重复:
Timer, event and garbage collection : am I missing something?
private void TrayForm_Load(object sender, EventArgs e)
{
System.Timers.Timer HideMeTimer = new System.Timers.Timer(2500);
HideMeTimer.Elapsed +=
delegate(object sender2, System.Timers.ElapsedEventArgs e2)
{
this.Invoke(new Action(somestuff));
};
HideMeTimer.Start();
GC.Collect();
}
有人可以告诉我编译器将如何翻译吗? 或者很好地解释为什么定时器在加载事件后继续滴答作响。
(当最后一个引用消失时,不是规则,变量,GC会在某个时间 杀死对象!)
答案 0 :(得分:12)
您需要了解System.Timers.Timer
在幕后所做的事情。它是System.Threading.Timer
类的包装器。当计时器启动时,它会创建一个新的System.Threading.Timer
实例,并在System.Timers.Timer
实例中传递一个回调方法。只要计时器保持启用状态,系统就会引用此回调委托。
我们也知道委托保留对包含目标方法的类的实例的引用。这就是为什么没有收集System.Timers.Timer
实例并且不会自动停止的原因。删除Elapsed
事件处理程序不会解决此问题,因为 委托仅保存对TrayForm
实例的引用。同样,System.Threading.Timer
保留了对System.Timers.Timer
的引用。整个参考链仍然是根的,因为系统必须引用System.Threading.Timer
才能使其工作。
以下是参考链:
System => _TimerCallback => Callback => System.Threading.Timer => Callback => System.Timers.Timer
当您使用Reflector或ILSpy跟踪此信息时,您可以看到上面参考链中的“系统”通过标记为TimerBase.AddTimerNative
的{{1}}方法发挥作用,因此我们无法确切了解引用根植于此点之下。但是,它仍然是根深蒂固的。
如果您通过MethodImplOptions.InternalCall
或Enabled = false
停用了计时器,那么它将处置基础Stop
,而System.Threading.Timer
又会停止引用System.Timers.Timer
。