【问题标题】:Clean Up Vs Memory Reclaim in .Net.Net 中的清理与内存回收
【发布时间】:2010-10-18 02:48:39
【问题描述】:
我正在阅读此 MSDN 参考:
虽然垃圾收集器能够
跟踪对象的生命周期
封装了一个非托管
资源,没有具体的
关于如何清理的知识
资源。对于这些类型的对象,
.NET 框架提供
Object.Finalize 方法,它允许
清理其非托管对象
资源妥善当垃圾
收集器回收使用的内存
物体。默认情况下,Finalize
方法什么都不做。如果你想要
垃圾收集器执行清理
在它之前对你的对象进行操作
回收对象的内存,你必须
覆盖您的 Finalize 方法
类。
我了解 GC 的工作原理,但这让我想到 CleanUp 到底是什么?如果它不是为什么它具有不同的名称,它只是在回收内存吗?
【问题讨论】:
标签:
c#
.net
garbage-collection
【解决方案1】:
请注意,这也不是全部,因为最终确定仅在对象被垃圾回收时发生。实际上,您应该尽快释放所有非托管资源(文件句柄、互斥体、非托管内存)。你应该看看IDisposable 接口,它定义了Dispose() 函数。
您的处理程序应尽可能运行与终结器相同的方法来释放资源,但随后调用 GC.SuppressFinalize() 以阻止它再次运行(在终结器中),因为使用实现的对象时性能会受到轻微影响终结者。
【解决方案2】:
他们使用了诸如“清理”之类的通用短语,因为除了回收内存之外,可能还需要做其他事情。我可以看到这可能有点令人困惑,因为引用在同一个句子中提到了清理资源和回收内存。在这种情况下,它们的意思是垃圾收集器回收托管代码使用的内存,这些代码实际调用到非托管库(例如包装类)中,但将非托管特定回收过程留给开发人员(关闭文件句柄、释放缓冲区等)。
例如,我有一个 Graphviz 包装库,其中包含一个 Graph 类。此类包装用于创建图形、向其添加节点等的函数。在内部,此类维护指向由 Graphiz 本身分配的非托管图形结构的指针。对于 .NET Framework,这只是一个IntPtr,它不知道如何在垃圾回收期间释放它。因此,当不再使用托管的Graph 对象时,垃圾收集器会释放指针使用的内存,但不会释放它指向的数据。为此,我必须实现一个终结器,它调用非托管函数agclose(释放图形使用的资源的 Graphviz 函数)。
【解决方案3】:
例如,如果您编写了一个使用某些操作系统资源(如命名管道或内存映射文件)的组件。您可以使用 finalize 操作将资源释放回操作系统。
【解决方案4】:
清理非托管资源可能包括关闭网络连接、文件、数据库连接等。当然,也可能包括为该资源释放内存。
【解决方案5】:
CleanUp 在这里意味着释放任何有限资源(硬盘、网络带宽、声卡、内存、CPU 等),并且由于 .NET 没有对非托管代码的托管引用,它可以让您在在 GC 交换之前使用 Finalize() 方法的正确时机。如果您不CleanUp,您最终会得到一些处于未知状态的孤儿非托管代码,这些代码仍在使用资源。最好通过在对象上调用Dispose() 来实现IDisposable 和CleanUp。