为什么本地捕获的计时器不会超出范围
本文关键字:范围 计时器 为什么 | 更新日期: 2023-09-27 18:15:28
可能重复:
计时器、事件和垃圾收集:我是不是遗漏了什么?
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有时会杀死物体!(
您需要了解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跟踪这一点时,你可以看到上面参考链中的"系统"是通过标记为MethodImplOptions.InternalCall
的TimerBase.AddTimerNative
方法发挥作用的,所以我们无法确切地看到参考是如何在这一点以下扎根的。但是,它是根深蒂固的。
如果您通过Enabled = false
或Stop
禁用计时器,则它将处理底层System.Threading.Timer
,后者将停止引用System.Timers.Timer
。