Alliberar recursos no manegats amb IDisposable

Amb .Net tenim recursos manegats i recursos no manegats. Els primers son els que gestiona el CLR mentre que els altres son externs al .Net i per tant no els gestiona el CLR. El CLR és el responsable de crear les classes i també destruir-les, demanant al Garbage Collection que escombri de la memòria totes aquelles referències que ja no s’utilitzen.

Amb els recursos no manegats trobem connexions a les bases de dades, connexions a xarxes, descriptors de fitxers i altres, com per exemple, el DispatcherTimer que amb WPF si no tanquem el rellotge aquest deixa vius els objectes que recullen l’event Tick.

IDisposable es la interfície que permet implementar el mètode Dispose. Aquest és el mètode estàndard amb .Net per alliberar els recursos manualment. Tenim els destructors de les classes que poden alliberar els recursos però aquest només és cridat per el GC i aquí perdem el control de quan pot passar això, ja que, és el SO qui determinarà si el GC pot escombrar o no.

Per implementar IDisposable existeix un patró que sempre hem de seguir.

// Design pattern for a base class.
public class Base: IDisposable
{
    private bool disposed = false;
    //Implement IDisposable.
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Free other state (managed objects).
            }
            // Free your own state (unmanaged objects).
            // Set large fields to null.
            disposed = true;
        }
    }
    // Use C# destructor syntax for finalization code.
    ~Base()
    {
        // Simply call Dispose(false).
        Dispose (false);
    }
}
// Design pattern for a derived class.
public class Derived: Base
{
    private bool disposed = false;
    protected override void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Release managed resources.
            }
            // Release unmanaged resources.
            // Set large fields to null.
           // Call Dispose on your base class.
            disposed = true;
        }
        base.Dispose(disposing);
    }
    // The derived class does not have a Finalize method
    // or a Dispose method without parameters because it inherits
    // them from the base class.
}

Aquesta informació la pots trobar a Implementing Finalize and Dispose to Clean Up Unmanaged Resources

GC.SuppressFinalize demana al GC que no executi el destructor per aquesta classe ja que la alliberació s’ha fet manual. Per tant, ja veus que el destructor d’una classe allibera els recursos quan nosaltres no ho hem fet manualment. I per què no es fa sempre així? Doncs perquè el GC ha de fer dues passades quan es troba un destructor i això fa més lent el procés de neteja.

Anuncis

Deixa un comentari

Fill in your details below or click an icon to log in:

WordPress.com Logo

Esteu comentant fent servir el compte WordPress.com. Log Out / Canvia )

Twitter picture

Esteu comentant fent servir el compte Twitter. Log Out / Canvia )

Facebook photo

Esteu comentant fent servir el compte Facebook. Log Out / Canvia )

Google+ photo

Esteu comentant fent servir el compte Google+. Log Out / Canvia )

S'està connectant a %s