2010-10-18 29 views
2

我读这个MSDN参考:清理Vs的内存回收在.net

虽然垃圾收集器能够 跟踪对象 封装非托管资源 的寿命,它没有具体的 关于如何清理 资源的知识。对于这些类型的对象, .NET框架提供了 Object.Finalize方法,它允许 一个目的是适当地清理其非托管 资源当垃圾 集电极回收由 对象使用的存储器。默认情况下,Finalize 方法不起作用。如果您希望 垃圾回收器在您的对象上执行清理操作 ,然后其 回收该对象的内存,则必须 覆盖您的 类中的Finalize方法。

我明白GC是如何工作的,但这让我想到了实际上CleanUp是什么?它是只是回收内存,如果它是为什么它有不同的名称?

回答

3

他们使用了一个通用的短语,比如“清理”,因为除了回收内存之外,其他的事情可能需要完成。我可以看到这可能有点令人困惑,因为引用提到清理资源和回忆同一句话中的记忆。在这种情况下,它们的意思是垃圾回收器回收托管代码使用的内存,该内存实际上调用到非托管库(例如,包装类)中,但将非托管特定的回收过程留给开发人员(关闭文件句柄,释放缓冲区等)。

举个例子,我有一个包含Graph类的Graphviz包装库。这个类包装了用于创建图的函数,为它们添加节点等。在内部,这个类保存了一个指向Graphiz自身分配的非托管图结构的指针。对于.NET Framework,这仅仅是一个IntPtr,它不知道如何在垃圾回收期间释放它。所以,当一个托管的对象不再被使用时,垃圾回收器释放指针使用的内存,但不释放它指向的数据。为此,我必须实现一个调用非托管函数agclose(Graphviz函数释放图形使用的资源)的终结器。

1

例如,如果您编写了一个使用某个操作系统资源(如命名管道或内存映射文件)的组件。您可以使用finalize操作将资源释放回操作系统。

0

清理非托管资源可能包括关闭网络连接,文件,数据库连接等。当然,它也可能包括为该资源解除分配内存。

0

CleanUp这里的意思是释放任何有界资源(硬盘,网络带宽,声卡,内存,CPU等),由于.NET没有托管引用非托管代码,它可以让你在在GC交换之前使用Finalize()方法自己正确的时刻。如果你不是CleanUp,你最终会得到一些处于未知状态的孤立非托管代码,这些代码仍在使用资源。通过在您的对象上调用Dispose()来实现IDisposableCleanUp会更好。

4

请注意,这不是完整的故事,因为最终确定只发生在对象被垃圾收集时。实际上,您应该尽快释放所有非托管资源(文件句柄,互斥锁,非托管内存)。您应该看看IDisposable接口,该接口定义了Dispose()函数。

只要有可能,您的垃圾处理器应该运行相同的方法来释放终结器所需的资源,但之后会调用GC.SuppressFinalize()以阻止其再次运行(在终结器中),因为使用实现终结器的对象时性能会受到很小的影响。