使用Dispose()方法

本文关键字:方法 Dispose 使用 | 更新日期: 2023-09-27 18:13:51

为什么我在发布模式下将timer.Dispose()添加到代码中时多次看到"Hello"字样。没有timer.Dispose(),我看到"Hello"一次。谢谢。

using System.Threading;
namespace ConsoleApplication1
{
    class Program
    {
        static void Method(object state)
        {
            Console.WriteLine(state);
            GC.Collect();
        }
        static void Main()
        {
            var timer = new Timer(Method, "Hello", 0, 200);
            Console.ReadLine();
            timer.Dispose();
        }
    }
}

使用Dispose()方法

您只看到一次,因为垃圾收集器已经收集了计时器对象。

由于没有更多的引用被认为是"活的",所以垃圾收集器可以自由地这样做。

在发布模式下,当没有附加调试器时,JITter建立关于在方法中使用局部变量的知识。一旦不再使用变量,如果方法当前在该点以下执行,则不再将其视为根。因此,垃圾收集器可以收集计时器对象。但是,在此之前,它必须完成对象,这将破坏底层计时器对象并阻止其执行。

在调试版本中,所有局部变量的作用域被人为地扩展为整个方法,这样如果你在方法中设置了一个断点,你就可以检查变量,即使程序实际上不再需要该变量存在。

当您添加dispose调用时,您延长了变量的生命周期,从而阻止了垃圾收集器收集计时器对象。

由于您在计时器事件处理程序方法中引发了垃圾收集,因此在本例中您实际上自己销毁了计时器。当您通过添加Dispose调用来扩展变量的生命周期时,垃圾收集器仍然作为计时器事件处理程序的一部分运行,但它还不能收集计时器,因此它继续运行。

Hans Passant留下的答案比我上面的蹩脚尝试描述得更好:

了解。net中的垃圾回收

我怀疑这是因为GC.Collect不会收集timer对象,当它仍然在当前代码行下面引用时。

timer.Dispose();在本例中的行为与GC.KeepAlive(timer);类似。

如果您同时删除DisposeGC.Collect(),您将得到一些"Hello",然后GC将决定自己收集,并且您将不会得到更多。