在.Net中清理Vs Memory Reclaim

时间:2010-10-18 02:48:39

标签: c# .net garbage-collection

我正在阅读此MSDN参考:

  

虽然垃圾收集器能够   跟踪对象的生命周期   封装了一个非托管的   资源,它没有具体的   关于如何清理的知识   资源。对于这些类型的对象,   .NET Framework提供了   Object.Finalize方法,允许   一个清理其未管理的对象   垃圾时适当的资源   收集器回收使用的内存   物体。默认情况下,Finalize   方法什么也没做。如果你想要的话   垃圾收集器执行清理   对象之前的操作   你必须回收对象的记忆   覆盖你的Finalize方法   类。

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

5 个答案:

答案 0 :(得分:4)

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

只要有可能,你的处理程序应该使用与终结器相同的方法来释放资源,但是然后调用GC.SuppressFinalize()来阻止它再次运行(在终结器中),因为在使用对象时会有轻微的性能损失实现终结者。

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

CleanUp在这里意味着释放任何有界资源(硬盘,网络带宽,声卡,内存,CPU等),并且由于.NET没有对非托管代码的托管引用,它可以让你做在GC交换它之前,在适当的时候自己使用Finalize()方法工作。如果你没有CleanUp,你将会在一个仍在使用资源的未知状态下找到一些孤立的非托管代码。最好通过调用对象上的IDisposable来实现CleanUpDispose()