Antonio Esposito's


Prodotti tipici .NETtiani

Evitare MemoryLeak

Ciao a tutti

Parlando dell'utilizzo di memoria e di un suo eventuale mancato rilascio (MemoryLeak), lo stesso codice può essere considerato corretto in un contesto monoutente magari client-server, ma meno corretto su un sistema web con molte più connessioni, o in scenari multi-tier. Un esempio:

class Person {
  public string Name {get; set;}
  public Person Kid {get; set;}
  public Person Dad {get; set;}
}

Bisogna sapere che con una classe così una grande quantità di oggetti con riferimenti incrociati potrebbe impedire il corretto funzionamento del GC (garbage collector), il componente del .NET (esiste anche in java) che fa da camion della raccolta rifiuti.. il suo compito è quello di distruggere oggetti inutilizzati. Ma come un camion non raccoglie niente se nessuno riempe i contenitori dei rifiuti in strada, così anche il GC non fa nessun collect degli oggetti se questi sono ancora in uso da altri oggetti e spesso questo non significa in uso da parte della nostra logica di controllo, ma semplicemente collegati ad altri come variabili.

L'approccio che consiglio è quello di implementare la IDisposable che garantisce la giusta distruzione degli oggetti senza dover aspettare che il GC faccia il suo giro di raccolta rifiuti, cosa che consuma CPU e non avviene finchè il sistema non lo reputa necessario (ad esempio è finita la RAM) e contemporaneamente utilizzare la classe WeakReference (riferimento debole) così da garantire la distruzione degli oggetti con riferimenti incrociati eventualmente dal GC se noi non possiamo utilizzare il costrutto using perchè ad esempio abbiamo una o più liste di oggetti che conserviamo in qualche sorta di cache applicativa o collection:

class WeakReference : WeakReference //mi creo un weakreference che supporti i generics (non necessario)
{
    public void WeakReference(T target) : base(target) {} // costruttore generico

    public virtual T Target
    {
        get {return (T)base.Target; }
        set {base.Target=value; }
    }
}

class Person : IDisposable {
  public string Name {get; set;}
  public WeakReference Dad {get; set;}
  public WeakReference Kid {get; set;} 

  void IDisposable.Dispose() { }
}

Sarebbe possibile mascherare l'uso dei WeakReference in questo modo:

class Person : IDisposable {
  public string Name {get; set;}
  private WeakReference _dad = new WeakReference(null);
  private WeakReference _kid = new WeakReference(null);

  public Person Dad {get { return _dad.Target; } set { _dad.Target=value; }}
  public Person Kid {get { return _kid.Target; } set { _kid.Target=value; }}

  void IDisposable.Dispose() { }
}

martedì, 19 gen 2010 Ore. 14.29
Statistiche
  • Views Home Page: 10.724
  • Views Posts: 58.957
  • Views Gallerie: 0
  • n° Posts: 44
  • n° Commenti: 16
Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003