使用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();
}
}
}
您只看到一次,因为垃圾收集器已经收集了计时器对象。
由于没有更多的引用被认为是"活的",所以垃圾收集器可以自由地这样做。
在发布模式下,当没有附加调试器时,JITter建立关于在方法中使用局部变量的知识。一旦不再使用变量,如果方法当前在该点以下执行,则不再将其视为根。因此,垃圾收集器可以收集计时器对象。但是,在此之前,它必须完成对象,这将破坏底层计时器对象并阻止其执行。
在调试版本中,所有局部变量的作用域被人为地扩展为整个方法,这样如果你在方法中设置了一个断点,你就可以检查变量,即使程序实际上不再需要该变量存在。
当您添加dispose调用时,您延长了变量的生命周期,从而阻止了垃圾收集器收集计时器对象。
由于您在计时器事件处理程序方法中引发了垃圾收集,因此在本例中您实际上自己销毁了计时器。当您通过添加Dispose调用来扩展变量的生命周期时,垃圾收集器仍然作为计时器事件处理程序的一部分运行,但它还不能收集计时器,因此它继续运行。
Hans Passant留下的答案比我上面的蹩脚尝试描述得更好:
了解。net中的垃圾回收
我怀疑这是因为GC.Collect
不会收集timer
对象,当它仍然在当前代码行下面引用时。
timer.Dispose();
在本例中的行为与GC.KeepAlive(timer);
类似。
如果您同时删除Dispose
和GC.Collect()
,您将得到一些"Hello",然后GC将决定自己收集,并且您将不会得到更多。