2008-09-22 3 views
11

Welche Ressourcen müssen in C# manuell bereinigt werden und was sind die Konsequenzen, wenn Sie dies nicht tun?Ressourcen, die in C# manuell bereinigt werden müssen?

Zum Beispiel sagen, ich habe den folgenden Code:

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black); 
// Use Brush 

Wenn ich aufzuräumen nicht die Bürste die dispose-Methode verwendet wird, gehe ich davon aus der Garbage Collector gibt den Speicher bei Programmende verwendet? Ist das richtig?

Welche anderen Ressourcen muss ich manuell bereinigen?

Antwort

1

Technisch alles, was von IDisposable erbt sollte proaktiv entsorgt werden. Sie können die 'using'-Anweisung verwenden, um die Dinge zu vereinfachen.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Manchmal werden Sie inkonsistente Verwendung von IDisposable abgeleiteten Objekte in der Dokumentation Beispielcode sowie Code sehen, die durch Tools (das heißt Visual Studio) erzeugt wird.

Was ist schön an IDisposable ist, dass es Ihnen die proaktiv Freigabe der zugrunde liegenden nicht verwalteten Ressource gibt. Manchmal möchten Sie das wirklich - denken Sie zum Beispiel an Netzwerkverbindungen und Dateiressourcen.

7
  • Handles zu internen Windows-Datenstrukturen.
  • Datenbankverbindungen.
  • Datei-Handles.
  • Netzwerkverbindungen.
  • COM/OLE-Referenzen.

Die Liste geht weiter.

Es ist wichtig, Dispose oder noch besser, verwenden Sie die using Muster.

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black)) 
{ 
    // use myBrush 
} 

Wenn Sie etwas nicht schaffen Sie, wird es gereinigt werden, wenn die Garbage Collector bemerkt, dass keine weiteren Hinweise darauf gibt, die nach einiger Zeit sein kann.

Im Fall System.Drawing.Brush speichert Windows interne Windows-Strukturen für den im Speicher geladenen Pinsel, bis alle Programme ihren Griff freigeben.

2

Im Allgemeinen sollte alles, was IDisposable implementiert, dazu führen, dass Sie die Ressource, die Sie verwenden, anhalten und untersuchen.

GC tritt nur auf, wenn Speicherdruck vorhanden ist, daher kann nicht vorhergesagt werden, wann. Obwohl ein Entladen der AppDomain es sicherlich auslösen wird.

-3

Der Garbage Collector behandelt verwaltete Ressourcen. In Ihrem Beispiel wird der Pinsel bereinigt, wenn der Garbage Collector entscheidet, was einige Zeit nach dem letzten Verweis auf den Pinsel nicht mehr gültig sein wird.

Es gibt bestimmte Dinge, die manuell bereinigt werden müssen, aber es handelt sich um Zeiger, die aus nicht verwalteten Quellen wie DLL-Aufrufen abgerufen werden. Nichts in .NET Framework benötigt diese Behandlung jedoch.

+0

Diese Antwort sollte erklären, wann Sie Ihre Ressourcen aufräumen müssen, nicht wann Sie sollten, wie andere es getan haben. Aus dem Ton der ursprünglichen Frage ging ich hervor, dass dies das Gewünschte war. – Guvante

0

Nun, solange Sie die verwaltete Version der Ressourcen verwenden und die Windows-APIs nicht selbst aufrufen, sollten Sie in Ordnung sein. Sorgen Sie sich nur darum, eine Ressource löschen/zerstören zu müssen, wenn Sie ein IntPtr erhalten, da "Windows-Handles" (und eine ganze Menge anderer Dinge) in .NET bekannt sind und kein Objekt.

Übrigens wird die Ressource (wie jedes andere .NET-Objekt) zum Sammeln markiert, sobald Sie den aktuellen Kontext verlassen. Wenn Sie also den Pinsel innerhalb einer Methode erstellen, wird er beim Beenden markiert .

7

Wenn Sie etwas nicht entsorgen, wird es bereinigt, wenn der Garbage Collector bemerkt, dass es in Ihrem Code keine Referenzen mehr gibt, was nach einiger Zeit der Fall sein kann. Für so etwas ist es nicht wirklich wichtig, aber für eine offene Datei tut es das wahrscheinlich.

Im Allgemeinen, wenn etwas eine Dispose-Methode hat, sollten Sie es nennen, wenn Sie mit ihm fertig sind, oder, wenn Sie können, wickeln Sie es in einer using Anweisung up:

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black)) 
{ 
    // use myBrush 
} 
0

Wenn es verwaltet wird (dh Teil des Rahmens) müssen Sie sich keine Sorgen machen. Wenn es IDisposable implementiert, wickle es einfach in einen using Block.

Wenn Sie nicht verwaltete Ressourcen verwenden möchten, müssen Sie die Finalisierer lesen und IDisposable selbst implementieren.

Es gibt viel mehr Detail unter this question

0

Bei der Beendigung des Programms können Sie davon ausgehen, dass der vom Prozess verwendete Speicher mit dem Prozess selbst gelöscht wird.

Bei der Verwendung von dispose oder destructor in.net muss man verstehen, dass der Zeitpunkt, zu dem die Dispose-Funktion vom GC aufgerufen wird, nicht deterministisch ist. Deshalb wird empfohlen, die Verwendung explizit zu verwenden oder dispose aufzurufen.

Bei der Verwendung von Ressourcen wie Dateien müssen Speicherobjekte wie Semaphore und Ressourcen außerhalb der verwalteten Welt von .net freigegeben werden.

Der SolidBrush zum Beispiel müssen Sie entsorgen, weil es ein GDI-Objekt ist und außerhalb der .net-Welt lebt.

0

Der Garbage Collector gibt nicht nur beim Beenden des Programms frei, sonst wäre es nicht wirklich nützlich (auf jedem vernünftigen/aktuellen OS, wenn der Prozess beendet wird, wird sein gesamter Speicher automatisch vom Betriebssystem aufgeräumt).

Einer der großen Vorteile von C# im Vergleich zu C/C++ ist, dass Sie sich nicht darum kümmern müssen, die zugewiesenen Objekte freizugeben (meistens); Das GC tut es, wenn die Laufzeit entscheidet (verschiedene Strategien wann/wie es gemacht wird).

Viele Ressourcen werden nicht betreut von der gc genommen: Datei, fadenbezogene Ressourcen (Schlösser), Netzwerkverbindungen, etc ...

3

Die Folgen nicht Ihre IDisposables Entsorgung von einem vernachlässigbaren Leistungseinbußen variieren kann um deine App zu stürzen.

Das Brush-Objekt in Ihrem Beispiel wird vom GC bereinigt, wenn es sich anfühlt. Aber Ihr Programm hätte nicht den Vorteil des zusätzlichen Speichers gehabt, den Sie durch eine frühere Bereinigung erhalten hätten. Wenn Sie viele Brush-Objekte verwenden, kann dies erheblich werden. Der GC ist auch bei der Säuberung von Objekten effizienter, wenn sie nicht sehr lang sind, da es sich um einen Generations-Garbage-Collector handelt.

Auf der anderen Seite können die Folgen der Nicht-Bereitstellung von Datenbankverbindungsobjekten dazu führen, dass Ihnen die Pool-Datenbankverbindungen sehr schnell ausgehen und Ihre App zum Absturz gebracht wird.

Entweder verwenden

using (new DisposableThing... 
{ 
    ... 
} 

Oder, wenn Sie einen Verweis auf ein IDisposable in Ihrem Objekt während seiner gesamten Lebensdauer zu halten brauchen, implementieren IDisposable auf Ihrem Objekt und rufen Sie die Dispose-Methode der IDisposable.

class MyClass : IDisposable 
{ 
    private IDisposable disposableThing; 

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... } 

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

    protected virtual void Dispose(bool disposing) 
    //etc... (see IDisposable on msdn) 

}

0

Ein Ort, vorsichtig zu sein, Objekte, die klein GC aussehen aber nicht ... In dem Sharepoint-API zum Beispiel hat das SPWeb Objekt einen geringen Platzbedarf so weit wie die GC ist betroffen und wird daher eine niedrige Priorität für die Sammlung haben, aber es hat wirklich eine Menge Speicher (auf dem Haufen, glaube ich) gepackt, von dem der GC nichts weiß. Sie werden in einige lustige Speicherprobleme geraten, wenn Sie zum Beispiel eine ganze Reihe davon vorwegnehmen, denken Sie immer daran, mit zu verwenden oder zu entsorgen!

1

Wie andere gesagt haben, ist die Verwendung Ihres Freundes. Ich schrieb this blog entry darüber, wie IDisposable in einer ziemlich direkten Art und Weise implementiert werden kann, die weniger fehleranfällig ist, indem die wichtigsten Teile herausgerechnet werden.

1

Ein Trick, den ich benutze, wenn ich kann mich nicht erinnern, ob ein bestimmtes Objekt eine Einweg-Ressource ist „.Dispose“ (höchstens!) Nach der Erklärung zu geben Intellisense zu bekommen für mich zu überprüfen:

MemoryStream ms = new MemoryStream().Dispose 

dann die .Dispose löscht und verwenden, um die Verwendung von() Richtlinie:

using(MemoryStream ms = new MemoryStream()) 
{ 
    ... 
} 
+0

Beachten Sie, dass dieser Trick nicht funktioniert, wenn Dispose explizit implementiert wurde! –

0

Anstatt als ein Objekt denken Ressourcen „Halt“, die freigegeben werden müssen, ist es besser, in Bezug auf ein Objekt zu denken, wie mit etwas verändert (möglicherweise außerhalb des Computers!), das es überleben wird, in gewisser Weise co udd schädlich sein, wenn es nicht rückgängig gemacht oder "aufgeräumt" wird, sondern nur das Objekt aufräumen kann. Während diese Änderung normalerweise die Form eines konkreten Objekts in einem Pool annimmt, das als "beschäftigt" markiert ist, spielt seine genaue Form keine Rolle. Es kommt darauf an, dass die Änderungen rückgängig gemacht werden müssen und das Objekt Informationen enthält, die dazu erforderlich sind.

Verwandte Themen