简体   繁体   English

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

[英]How does GC and IDispose work in C#?

I remember i was loading in images by streaming it from the net straight into a bitmap. 我记得我是通过从网络直接将其流化为位图来加载图像的。 close the stream, return the bitmap and held it in an image control. 关闭流,返回位图并将其保存在图像控件中。

I excepted when i did = loadPicture() the first bitmap would be freed like a smart pointer would do in C++. 我除外,当我做到= loadPicture()时,将像智能指针在C ++中那样释放第一个位图。 But it didnt and i consumed a lot of ram until i called dispose. 但是没有,我花了很多公羊,直到我打电话给处置。 So my question is. 所以我的问题是。

How does the GC and Dispose able objects work in C#? GC和Dispose能力对象如何在C#中工作? and why isnt it implemented like a smart_ptr? 为什么不像smart_ptr一样实现呢?

References are not smart pointers. 引用不是智能指针。 Letting a reference-variable go out of scope, replacing it with another value, and/or setting it with null all do exactly nothing . 让引用变量超出范围,将其替换为另一个值,和/或将其设置为null完全没有任何作用

This is simply part of the CLI /GC design... 这只是CLI / GC设计的一部分...

Gargage Collection (GC) will run when needed , and should clean up the managed memory used, and (if a finalizer is provided) any unmanaged resources too. 垃圾回收(GC)将在需要时运行,并且应清理所使用的托管内存,以​​及(如果提供了终结器)任何非托管资源。 But for deterministic cleanup: that is the entire purpose of IDisposable . 但是要进行确定性清理:这就是IDisposable的全部目的。 It is your job to Dispose() such objects when you have finished with them - either via using , or by handing it to something else which assumes this responsibility (common, for example, with streams/readers etc). 完成对此类对象的Dispose()是您的工作-通过using ,或将其移交给承担此责任的其他对象(例如,在流/阅读器等中很常见)。

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

The GC kicks in when the runtime feels it is necessary. 当运行时认为有必要时,GC将启动。

The basic rule is: when you use an Disposable type (IDispose), then you (as the programmer) should release the resources used by that type as soon as possible, by calling Dispose when you do not longer need to use that type. 基本规则是:当您使用Disposable类型(IDispose)时,您(作为程序员)应尽快释放该类型使用的资源,方法是在不再需要使用该类型时调用Dispose。 For instance, when you read a file, you close that file as soon as you've done reading it. 例如,当您读取文件时,一旦完成读取就关闭该文件。 (Calling close will also call dispose in this case). (在这种情况下,调用close也将调用dispose)。

You must call Dispose explicity on any object implementing IDisposable, otherwise your unmanaged resources will not be disposed . 您必须在实现IDisposable的任何对象上调用Dispose显式调用,否则您的非托管资源将不会被处置 If you don't want to call it explicity, then you must override the Finalize method to call the Dispose method - that is why you will see this frequently: 如果您不想显式调用它,则必须重写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 */
    }
 }

smart_ptr are reference counted. smart_ptr被引用计数。 While this allows for deterministic release of their resources when they are no longer referenced by any code, they do have their problems of their own: assigning references always requires the counter to be updated, circular references fail to be released automatically causing memory leaks, the memory manager is invoked more often. 尽管这样可以在不再被任何代码引用时确定释放其资源,但它们确实有其自身的问题:分配引用始终需要更新计数器,循环引用无法自动释放,从而导致内存泄漏,内存管理器被更频繁地调用。

The GC in .NET is a sweeping collector. .NET中的GC是一个全面的收集器。 It starts at any time when it feels that memory should be released (usually triggered by some memory usage condition, but not deterministic) and starts by building a list of all live references in the system (including the ones in CPU registers, nested references etc.). 它在感觉应该释放内存的任何时候开始(通常是由某些内存使用情况触发的,但不是确定性的),并从构建系统中所有活动引用(包括CPU寄存器中的引用,嵌套引用等)的列表开始。 )。 This works since we are in a managed environment where you cannot do pointer arithmetic etc. - the system can track all references. 这是可行的,因为我们处于无法执行指针算术等操作的托管环境中-系统可以跟踪所有引用。 After the list of live references has been built, it basically releases all memory not known to be used anymore. 构建实时引用列表之后,它基本上会释放所有未知的不再使用的内存。 Of course, this is just the basic sketch, for efficiency and management of unmanaged resources there is more to it like object generations, finalizers, etc., but that is not important for the basic understanding of how it works. 当然,这只是基本的草图,对于非托管资源的效率和管理,还有更多的东西,例如对象生成,终结器等,但这对于基本了解其工作原理并不重要。

The IDisposable interface is used to implement the disposable pattern, which helps when you are working with objects that should be disposed in a deterministic way. IDisposable接口用于实现一次性模式,这在处理应以确定性方式处理的对象时会有所帮助。 The pattern is so that Dispose() is called explicitly when the object is no longer needed, therefore releasing unmanaged resources or closing handles etc., but not releasing its memory. 这种模式使得在不再需要该对象时显式调用Dispose(),从而释放非托管资源或关闭句柄等,但不释放其内存。 This will be done by the GC later on, but it does not matter that this happens later, because the deterministic release of resources has already been performed. 稍后将由GC进行此操作,但是这不会在稍后发生,因为已经执行了确定性的资源释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM