2009-04-23 5 views
1

Ich erinnere mich, dass ich Bilder geladen habe, indem ich sie aus dem Netz direkt in eine Bitmap streamte. Schließen Sie den Stream, geben Sie die Bitmap zurück und halten Sie sie in einem Bildsteuerelement.Wie funktionieren GC und IDispose in C#?

I ausgenommen, wenn i = Loadpicture tat() die erste Bitmap würde wie ein Smart Pointer befreit werden würde in C++ tun. Aber es hat nicht funktioniert und ich habe viel Ram verbraucht bis ich angerufen habe. Also meine Frage ist.

Wie funktioniert die GC und Entsorgen der Lage, Objekte arbeiten in C#? und warum wird es nicht wie ein smart_ptr implementiert?

Antwort

2

Die GC Kicks, wenn die Laufzeit fühlt es notwendig ist. Die Grundregel lautet: Wenn Sie einen Disposable-Typ (IDispose) verwenden, sollten Sie (als Programmierer) die von diesem Typ verwendeten Ressourcen so schnell wie möglich freigeben, indem Sie Dispose aufrufen, wenn Sie nicht mehr benötigen dieser Typ. Wenn Sie beispielsweise eine Datei lesen, schließen Sie diese Datei, sobald Sie sie gelesen haben. (Calling Close wird in diesem Fall auch disponieren).

8

Referenzen sind keine Smartpointer. Lassen Sie eine Referenzvariable den Gültigkeitsbereich verlassen, ersetzen Sie sie durch einen anderen Wert, und/oder setzen Sie sie auf null, und tun Sie genau nichts.

Dieses einfach Teil des CLI/GC-Design ist ...

Gargage Collection (GC) wird laufen, wenn benötigt und sollte den verwalteten Speicher verwendet, und (wenn ein Finalizerthread vorgesehen ist) aufzuräumen auch nicht verwaltete Ressourcen. Aber für deterministische Aufräumarbeiten: das ist der ganze Zweck von IDisposable. Es ist Ihre Aufgabe zu Dispose() solche Objekte, wenn Sie mit ihnen fertig sind - entweder über using, oder durch etwas anderes übergeben, die diese Verantwortung (gemeinsam, beispielsweise mit streams/Leser etc.) übernimmt.

+0

+1. Ich bin mir sicher, dass diese Frage bereits gestellt wurde :) –

+0

Willst du damit sagen, dass ich nichts "wegschaffen" muss? –

+0

Nur in dem Sinne, dass selbst dann, wenn Sie dies nicht tun, Ressourcen freigegeben werden (wenn sie IDisposable korrekt implementieren). In der Praxis ist dies lediglich ein Sicherheitsnetz. Sie möchten nicht verwaltete Ressourcen so schnell wie möglich freigeben. –

0

smart_ptr sind Referenz gezählt. Während dies eine deterministische Freigabe ihrer Ressourcen ermöglicht, wenn sie von keinem Code mehr referenziert werden, haben sie ihre eigenen Probleme: das Zuweisen von Referenzen erfordert immer, dass der Zähler aktualisiert wird, zirkuläre Referenzen nicht automatisch freigegeben werden und Speicherlecks verursachen Der Speichermanager wird häufiger aufgerufen.

Die GC in .NET ist ein mitreißender Sammler. Es beginnt zu jeder Zeit, wenn es sich anfühlt, dass Speicher freigegeben werden sollte (normalerweise durch eine Speicherbenutzungsbedingung ausgelöst, aber nicht deterministisch) und beginnt mit dem Erstellen einer Liste aller Live-Referenzen im System (einschließlich denen in CPU-Registern, verschachtelten Referenzen, etc .). Dies funktioniert, da wir uns in einer verwalteten Umgebung befinden, in der Sie keine Zeigerarithmetik usw. ausführen können. Das System kann alle Referenzen verfolgen. Nachdem die Liste der Live-Referenzen erstellt wurde, werden im Prinzip alle Speicher freigegeben, die nicht mehr verwendet werden. Natürlich ist dies nur die Grundskizze, für die Effizienz und Verwaltung von nicht verwalteten Ressourcen gibt es mehr wie Objektgenerationen, Finalizer usw., aber das ist nicht wichtig für das grundlegende Verständnis dessen, wie es funktioniert.

Die IDisposable-Schnittstelle wird verwendet, um das Einweg-Muster zu implementieren, die hilft, wenn Sie mit Objekten arbeiten, die in einer deterministischen Art und Weise entsorgt werden. Das Muster ist so, dass Dispose() explizit aufgerufen wird, wenn das Objekt nicht mehr benötigt wird, also nicht verwaltete Ressourcen freigibt oder Griffe usw. schließt, aber seinen Speicher nicht freigibt. Dies wird später von der GC gemacht, aber es spielt keine Rolle, dass dies später passiert, weil die deterministische Freigabe von Ressourcen bereits durchgeführt wurde.

1

Sie müssen Dispose explicity für jedes Objekt aufrufen, das IDisposable implementiert, andernfalls werden Ihre nicht verwalteten Ressourcen nicht entsorgt. Wenn Sie es nicht explizit aufrufen möchten, müssen Sie die Finalize-Methode überschreiben, um die Dispose-Methode aufzurufen. Daher wird dies häufig zu sehen sein: