2010-09-19 45 views
2

这里是一个代码执行意想不到的点可能会出现约GC一大篇:我怎样才能重现此.NET垃圾收集情况

终身,GC.KeepAlive,拉手回收 - 由cbrumme http://blogs.msdn.com/b/cbrumme/archive/2003/04/19/51365.aspx?wa=wsignin1.0

我的问题是如何在文章中提到的点再现强制GC?我尝试在OperateOnHandle()的开头放置GC.Collect(),并为类C定义了析构函数,但似乎不起作用。析构函数总是在程序结束时被调用。

@Jon,谢谢你建议我用尽调试器。现在我能够使用调试器优化的Release版本来重现文章中描述的问题。它证明了自从.NET v1以来,GC的行为不会改变。

码我用:

class C1 
{ 
    // Some unmanaged resource handle 
    IntPtr _handle = IntPtr.Zero; 

    static void OperateOnHandle(IntPtr h) 
    { 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 

     Console.WriteLine("After GC.Collect() call"); 

     // Use the IntPtr here. Oops, invalid operation 
    } 

    public void m() 
    { 
     OperateOnHandle(_handle); 
    } 

    ~C1() 
    { 
     // Release and destroy IntPtr here 
     Console.WriteLine("In destructor"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     C1 aC = new C1(); 
     aC.m(); 
    } 
} 

输出:

在析构函数 GC.Collect的()调用之后

+0

这是一篇旧文章(2003),所以很可能后一版本的.Net Framework会导致不同的行为。 – 2010-09-19 11:43:53

+0

这篇文章真的是关于SafeHandle的。他还不能透露。 – 2010-09-19 12:16:22

+0

@Hans,是的,你是对的。这完全关乎SafeHandler。 – Sheen 2010-09-19 22:45:11

回答

2

记住,这篇文章是从2003年,这是使用CLR V1 。我们现在使用CLR v4(虽然没有v3),所以我并不完全感到惊讶,你没有看到完全相同的行为。

目前我甚至无法进入链接页面,而且您还没有包含页面描述内容的描述。在实例方法结束之前是否有可能收集垃圾对象?

如果是这样,那么您可能有问题的最明显的原因是如果您使用调试器。垃圾回收器是,当你在没有附加调试器的情况下运行时,其他更具攻击性。

下面是一个简短而完整的程序在调试器不运行时,这表明该问题:

using System; 

class ClassWithFinalizer 
{ 
    private int value; 

    public ClassWithFinalizer(int value) 
    { 
     this.value = value; 
    } 

    ~ClassWithFinalizer() 
    { 
     Console.WriteLine("Finalizer running!"); 
    } 

    public void ShowValue() 
    { 
     Console.WriteLine(value); 
     Console.WriteLine("Calling GC.Collect()"); 
     GC.Collect(); 
     Console.WriteLine("Calling GC.WaitForPendingFinalizers()"); 
     GC.WaitForPendingFinalizers(); 
     Console.WriteLine("End of method"); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     var x = new ClassWithFinalizer(10); 
     x.ShowValue(); 
    } 
} 

汇编(优化,没有调试符号,只是为了给它的最好机会!):

csc /o+ /debug- Test.cs 

现在运行,具有输出:

c:\users\Jon\Test>test 
10 
Calling GC.Collect() 
Calling GC.WaitForPendingFinalizers() 
Finalizer running! 
End of method 

注意如何终结运行是该方法已完成。

经测试与.NET 4和.NET 3.5。

+0

在Main()的末尾放置Console.ReadLine()来重现OP的问题。 – 2010-09-19 12:15:42

+0

@Hans:Nope ...我刚刚把Console.ReadLine()和结束,它的行为方式是一样的。在方法结束之前调用终结器。 – 2010-09-19 12:32:24

+0

谢谢你的例子。 – Sheen 2010-09-19 22:45:39