【发布时间】:2010-08-30 01:12:16
【问题描述】:
如果我有一个活动的System.Threading.Timer 并将其设置为 null,它会停止吗?
我知道打电话给.Dispose() 更合适,但我希望得到书面问题的答案。
public class Foo
{
private System.Threading.Timer _timer;
public Foo()
{
// initialize timer
}
public void KillTimer()
{
_timer=null;
}
}
更新:
经过反复讨论是否将对 System.Threading.Timer 的单个引用设置为 null 确实会导致停止它,这表明
- 没有延迟引用,例如事件列表,因为线程计时器采用单一回调并且不公开事件。
- 如果 GC 收集,finalizer 确实会释放 TimerBase 并停止计时器。
尖峰
using System;
using System.Threading;
namespace SO_3597276
{
class Program
{
private static System.Threading.Timer _timer;
static void Main(string[] args)
{
_timer = new Timer((s) => Console.WriteLine("fired"), null, 1000, Timeout.Infinite);
_timer = null;
GC.Collect();
Console.ReadKey();
}
}
}
不调用定时器回调。删除GC.Collect() 并调用回调。
谢谢大家。
【问题讨论】:
-
为什么您认为仅仅因为您将变量设置为 null 就不再有对 Timer 的引用?大概 Timer 已被添加到某些系统事件队列中,以便注意到 Timer 何时触发。你知道那个事件队列是否使用 WeakReference 来引用 Timer 吗? (WeakReference是Java的概念:不知道.NET有没有类似的概念)
-
@adrian - 是的,.net 有 System.WeakReference。关于您的问题:上面的代码证明没有更多的引用,否则计时器将在 readkey 块中触发 1 秒。在更技术性的说明中,当创建计时器时,回调最终会被提供给
private extern void AddTimerNative。显然,通常是 .net 委托的内容是在非托管代码中处理的,而不是被视为引用。我不会假装完全理解那里发生的事情,但与上面的代码相关是有意义的。我希望能对此进行更多讨论。 -
@adrian - 并且盲目地向问题投掷飞镖,在我看来,突出的问题是它是一个函数指针,它是一个被传递的函数指针,而不是一个委托,因此没有引用计时器。
标签: c#