GC和IDispose如何在C#中工作?

时间:2009-04-23 08:51:02

标签: c# .net idisposable

我记得我是通过将它从网络直接流式传输到位图来加载图像。关闭流,返回位图并将其保存在图像控件中。

我除了当我执行= loadPicture()时,第一个位图将被释放,就像智能​​指针在C ++中一样。但它没有,我消耗了很多公羊,直到我打电话给处理。所以我的问题是。

GC和Dispose able对象如何在C#中运行?为什么它不像smart_ptr那样实现?

4 个答案:

答案 0 :(得分:8)

引用不是智能指针。让引用变量超出范围,将其替换为另一个值,和/或将其设置为null都完全 nothing

这只是CLI / GC设计的一部分......

Gargage Collection(GC)将在需要时运行 ,并且应该清理所使用的托管内存,并且(如果提供了终结器)也可以清除任何非托管资源。但对于确定性清理:这是IDisposable的全部目的。当你完成它们时,Dispose()这些对象是你的工作 - 通过using,或者把它交给承担这个责任的其他东西(常见的,例如,使用流/读者等)

using (StreamReader reader = new StreamReader(myfile)))
{
   ...
}

答案 1 :(得分:2)

当运行时认为有必要时,GC会启动。

基本规则是:当你使用Disposable类型(IDispose)时,你(作为程序员)应该尽快释放该类型使用的资源,当你不再需要使用它时调用Dispose类型。 例如,当您读取文件时,您在阅读完文件后立即关闭该文件。 (在这种情况下,呼叫关闭也会调用dispose。)

答案 2 :(得分:1)

您必须在实现IDisposable的任何对象上调用Dispose explicity,否则您的非托管资源将不会被释放。如果您不想将其称为明确,那么您必须覆盖Finalize方法以调用Dispose方法 - 这就是您经常会看到这一点的原因:

 class MyClass : IDisposable
 {
    ...

    ~MyClass()
    { 
       this.Dispose(false);
    }

    public void Dispose()
    {
       this.Dispose(true);
       GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        { /* dispose managed stuff also */ }

        /* but dispose unmanaged stuff always */
    }
 }

答案 3 :(得分:0)

smart_ptr是引用计数。虽然当它们不再被任何代码引用时,它允许确定性地释放它们的资源,但它们确实存在它们自己的问题:分配引用总是需要更新计数器,循环引用无法自动释放导致内存泄漏,内存管理器被更频繁地调用。

.NET中的GC是一个全面的收集器。它始于任何时候它感觉应该释放内存(通常由一些内存使用情况触发,但不是确定性),并通过构建系统中所有实时引用的列表(包括CPU寄存器中的内容,嵌套引用等)开始)。这是有效的,因为我们处于无法进行指针运算等的托管环境中 - 系统可以跟踪所有引用。在构建了实时引用列表之后,它基本上释放了所有未知的内存。当然,这只是基本的草图,对于非托管资源的效率和管理,它更像是对象生成,终结器等,但这对于它如何工作的基本理解并不重要。

IDisposable接口用于实现一次性模式,这有助于在处理应以确定方式处置的对象时使用。该模式是在不再需要对象时显式调用Dispose(),因此释放非托管资源或关闭句柄等,但不释放其内存。这将在稍后由GC完成,但是后来发生这种情况并不重要,因为已经执行了资源的确定性释放。