2012-08-25 11 views
22

Ich habe eine Klasse mit umfangreichen statischen Mitgliedern, von denen einige Verweise auf verwaltete und nicht verwaltete Objekte behalten.Wie und wann sind C# statische Elemente entsorgt?

Zum Beispiel wird der statische Konstruktor aufgerufen, sobald der Typ Bezug genommen wird, die meine Klasse verursacht eine Blocking von Aufgaben spin up. Dies geschieht beispielsweise, wenn eine der statischen Methoden aufgerufen wird.

Ich habe IDisposable implementiert, was mir Methoden zur Verfügung stellt, um die Beseitigung von allen Instanzobjekten zu behandeln, die ich erstellt habe. Diese Methoden werden jedoch nie aufgerufen, wenn der Konsument keine Instanzobjekte aus meiner Klasse erstellt.

Wie und wo kann ich Code setzte die vom statischen Teil meiner Klasse gehalten zu entsorgen? Ich dachte immer, dass die Entsorgung von Ressourcen mit statischer Referenz erfolgte, als das letzte Instanzobjekt freigegeben wurde. Dies ist das erste Mal, dass ich eine Klasse erstellt habe, in der niemals Instanzen erstellt werden können.

+1

Statische Elemente sind für die gesamte Ausführung der Anwendung zur Verfügung. Sie erstellen keine statischen Elemente, indem Sie das Schlüsselwort NEW verwenden. Dies bedeutet, dass Sie nicht mehrere Instanzen von irgendetwas haben, da Sie tatsächlich nichts instanziieren. Über verwaltete Objekte, mach dir keine Sorgen um sie, der GC wird sich um sie kümmern. Über nicht verwaltete Ressourcen versuchen, sie in einer nicht statischen Klasse zu verwenden, oder sie werden beibehalten, bis Sie Ihre Anwendung schließen. Statische Elemente unterstützen keine Entsorgung. – alexandrudicu

+0

Danke. Sieht so aus, als müsste ich mein Design hier überdenken. – Joe

Antwort

35

Die statische Variable Ihrer Klasse wird erst dann abgemagert, wenn die Anwendungsdomäne, die Ihre Klasse hostet, entladen wird. Die Methode Dispose() wird nicht aufgerufen, da es sich um eine Instanzmethode handelt, und Sie haben angegeben, dass Sie keine Instanzen Ihrer Klasse erstellen möchten.

Wenn Sie möchten, dass die Verwendung der Dispose() Methode machen, Ihr Objekt einen Singleton machen, erstellen Sie eine Instanz davon, und entsorgen Sie es ausdrücklich, wenn die Anwendung im Begriff ist, zu verlassen.

public class MyClass : IDisposable { 
    public IList List1<int> {get; private set;} 
    public IDictionary<string,string> Dict1 {get; private set;} 
    public void Dispose() { 
     // Do something here 
    } 
    public static MyClass Instance {get; private set;} 
    static MyClass() { 
     Instance = new MyClass(); 
    } 
    public static void DisposeInstance() { 
     if (instance != null) { 
      Instance.Dispose(); 
      Instance = null; 
     } 
    } 
} 
+0

Das macht Sinn. Ich vermutete, dass ich eventuell ein Singleton-Geplapper verwenden müsste ... danke für deine Hilfe. – Joe

0

Sie sollten diese Objekte manuell entsorgen, es gibt keine Möglichkeit, einen "Finalizer" für statische Ressourcen zu erstellen.

+1

Wie würde ich sie manuell entsorgen? Wie werde ich benachrichtigt, dass ich dies tun muss? – Joe

+0

@Joe Das liegt ganz bei Ihnen zu entscheiden. Nur Sie wissen, wann es Zeit ist, Dispose von etwas zu geben, das statisch gehalten wird. – vcsjones

+0

Sehen Sie sich zum Beispiel das Beispiel in der Originalfrage an, wo ich eine blockingQueue von Aktionen hochfahre. Diese Warteschlange sollte so lange ausgeführt werden, bis der Benutzer keine Aktionen mehr in die Warteschlange einfügen möchte (über die statische Methode). Lassen Sie mich das klarer machen; Wann erledige ich die Aufgabe, die diese Warteschlange abbaut? Also, wann töte ich es? Woher weiß ich, dass meine Klasse nicht mehr im "Geltungsbereich" für den Benutzer liegt? – Joe

0
public class Logger : IDisposable 
{ 

    private string _logDirectory = null; 
    private static Logger _instance = null; 

    private Logger() : this(ConfigurationManager.AppSettings["LogDirectory"]) 
    { 
     AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; 
    } 

    private Logger(string logDirectory) 
    { 
    } 

    public static Logger Instance 
    { 
     get 
     { 
      if (_instance == null) 
       _instance = new Logger(); 
      return _instance; 
     } 
    } 

    private void CurrentDomain_ProcessExit(object sender, EventArgs e) 
    { 
     Dispose(); 
    } 



    public void Dispose() 
    { 
     // Dispose unmanaged resources 
    } 
}