如何重现此.NET垃圾收集方案

时间:2010-09-19 11:38:26

标签: .net garbage-collection

以下是关于GC的一篇很棒的文章可能会在意外的代码执行点发生:

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

我的问题是如何在文章中提到的点重现强制GC?我试图将GC.Collect()放在OperateOnHandle()的开头,并为类C定义了析构函数,但似乎无法正常工作。总是在程序结束时调用析构函数。

@Jon,谢谢你建议我用完调试器。现在,我可以使用调试器的优化版本构建重现本文中描述的问题。它证明了自.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()之后调用

1 个答案:

答案 0 :(得分: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进行测试。

相关问题