在.Net C中释放资源#

时间:2010-05-04 09:13:42

标签: c# .net memory-leaks resources

我是C#和.NET的新手,并且一直在阅读它。

我需要知道为什么以及何时需要释放资源?垃圾收集器不能处理所有事情吗?我什么时候需要实现IDisposable,它与C ++中的析构函数有何不同?

另外,如果我的程序相当小,即屏幕保护程序,我是否需要关心释放资源?

感谢。

6 个答案:

答案 0 :(得分:15)

垃圾收集器只知道内存。这对内存来说很好,因为只要你有足够的内存,一点内存几乎和其他内存一样好。 (这是所有模缓存一致性等。)

现在将其与文件句柄进行比较。操作系统可以有足够的空间来分配更多的文件句柄 - 但是如果你留下了一个特定文件的句柄,那么其他任何人都无法打开该特定文件进行写入。一旦完成,你应该告诉系统你何时完成一个句柄 - 通常是通过关闭相关的流 - 并且即使抛出异常也会以关闭它的方式这样做。这通常使用using语句完成,这类似于try / finally,在finally块中调用Dispose

C ++中的析构函数非常与.NET终结符不同,因为C ++析构函数是确定性的 - 例如,当相关变量超出范围时,它们会被自动调用。在一个对象不再被任何“实时”对象引用之后,终结器由垃圾收集器在某个时刻运行,但是时间是不可预测的。 (在极少数情况下,它可能从不发生。)

如果您有任何清理应该确定性地执行,您应该自己实施IDisposable - 通常情况是,如果您的实例变量之一实现IDisposable。现在很少需要自己实现终结器 - 如果你有一个直接保持操作系统句柄,通常只需要一个IntPtr; SafeHandle使所有这一切变得更加轻松,让您不必自己编写终结器。

答案 1 :(得分:2)

资源有两种 - 托管和非托管。如果你允许,垃圾收集器将清理托管资源 - 也就是说,如果你释放对该对象的任何引用。但是,垃圾收集不知道如何释放托管对象保存的非托管资源 - 例如文件句柄和其他OS资源。

当您希望及时发布托管资源(如数据库连接)时,IDisposable是最佳做法,并且当您需要释放非托管资源时,这是至关重要的。典型的模式:

public void Dispose()
protected void Dispose(bool disposing)

允许您确保通过Dispose方法或对象最终确定释放非托管资源。

答案 2 :(得分:2)

基本上,您需要担心将资源释放到非托管代码 - .NET框架之外的任何内容。例如,数据库连接或OS上的文件。

垃圾收集器处理托管代码 - .NET框架中的代码。

即使是小型应用程序也可能需要释放非托管资源,例如它可能会写入本地文本文件。完成资源后,需要确保调用对象的Dispose方法。 using语句简化了语法:

using (TextWriter w = File.CreateText("test.txt"))
{
    w.WriteLine("Test Line 1");
}

TextWriter对象实现了IDisposable接口,因此一旦使用块完成,就会调用Dispose方法并且可以对对象进行垃圾回收。收集的实际时间无法保证。

如果您创建自己需要正确处理的类,则需要自己实现IDisposable接口和Dispose模式。在一个简单的应用程序中,您可能不需要这样做,如果您this是一个很好的资源。

答案 3 :(得分:1)

您不需要在托管对象(如字符串或数组)中释放内存 - 这是由垃圾收集器处理的。

完成使用后,您应该清理操作系统资源和一些非托管对象。如果您打开文件,则应始终记得在使用完毕后关闭该文件。如果您专门打开文件而忘记关闭,则下次尝试打开该文件时,它可能仍会被锁定。如果某些东西实现了IDisposable,你一定要考虑是否需要正确关闭它。文档通常会告诉您Dispose方法的作用以及何时应该调用它。

如果你忘记了,垃圾收集器最终会运行终结器,它应该正确清理对象并释放非托管资源,但这不会在对象符合垃圾收集条件后立即发生,事实上它可能不会一直跑。

了解using声明也很有用。

答案 4 :(得分:0)

垃圾收集器释放MEMORY并清理 - 通过处置 - 删除elemet。但是:只有在内存压力下才会这样做。

对于我可能希望明确释放它们的资源来说,这是非常愚蠢的。例如,保存到文件应该是:打开文件,写出数据并 - 关闭文件,以便用户可以在需要时将其复制掉,而无需等待GC出现并释放内存对于文件对象,这可能不会发生几个小时。

答案 5 :(得分:0)

您只需要担心宝贵的资源。您在编程时创建的大多数对象都不适合此类别。如你所说,垃圾收集器会处理这些。

你需要注意的是实现IDisposable的对象,这表明它拥有的资源是宝贵的,不应该等待清理终结器线程。您需要实现IDisposable的唯一时间是拥有a)实现IDisposable的对象(例如文件流)或b)非托管资源的类。