2010-03-31 49 views
3

我有一段这样的代码:GC如何在.NET中收集静态成员中的资源?

Class Program 
{ 
    static StreamReader sr = null; 
    static int var=0; 
    static Program() 
    { 
     sr = new StreamReader("input.txt") 
    } 

    ~Program() 
    { 
     sr.Dispose(); 
    } 

    static void main(string args[]) 
    { 
     //do something with input here 
    } 
} 

这可能不是一个很好的做法,但我只是想用这个例子来问解构和GC是如何工作的。

我的问题是:Will〜Program()会在非确定的时间被调用,或者在这种情况下根本不会被调用。如果解构器不会被调用,那么GC如何收集非托管资源和管理资源。

回答

1

它可能不会回收这些资源,直到AppDomain或进程卸载。

如果你永远不会实例化一个对象,它将永远不会被销毁。这正是你想要的东西,可能就像一个单身人士。我相信有一种叫做“Phoenix Singleton”的味道,它可以让Singleton得到清理,然后在需要时重建。你可以使用WeakReference来实现它到单例对象。

在任何情况下,对于运行一段有限时间的简单程序,除非它成为问题,否则我不会担心它......当进程退出时资源将被清理。

1

您的情况还不太清楚,因为如果不创建类的实例,则不会调用终结器。

但是,只调用dispose对对象本身的垃圾收集没有任何影响,它只是告诉对象释放任何资源(特别是句柄等)。因此,如果您希望GC收集实例,则需要将参考设置为null,并且如果没有其他实例的实时引用,它最终将被收集。

基本上每个静态引用都可以看作是根引用,它被包含在GC检查活动引用中。无法通过实时参考(直接或间接)达到的所有实例都是收集的候选对象。如果引用“变量”是静态的或不是静态的。

1

静态引用将为实例创建根目录,直到它明确设置为null或其程序集被卸载。如果这两种情况都不发生,则静态参考指向的实例将继续使用,因此不会收集。如果它不符合垃圾收集条件,它的终结器也不会被调用。

btw GC只处理托管内存。它不处理非托管资源。为此你需要IDiposable和/或终结器。

1

C#中没有静态终结器(析构函数)。因此,除非实际创建了Program的实例,否则将永远不会将~Program()称为

当(如果)它被调用时,它只调用StreamReaderDispose()方法;因为在调用终结器之后仍然保留对StreamReader的引用,所以在程序退出之前,实例将永远不会被垃圾收集。