c # Speicherzuweisungs- und -freigabe-Muster

8

Da C # Garbage Collection verwendet. Wann muss .Dispose verwendet werden, um den Speicher freizugeben?

Ich weiß, dass es ein paar Situationen gibt, also werde ich versuchen, diejenigen aufzulisten, die mir einfallen.

  1. Wenn ich ein Formular schließe, das ein GUI-Objekt enthält, werden diese Objekte dereferenziert und daher gesammelt?
  2. Wenn ich ein lokales Objekt unter Verwendung von new erstelle, sollte ich .Dispose davon, bevor die Methode beendet wird oder einfach den GC darauf achten lassen? Was ist in diesem Fall eine gute Praxis?
  3. Gibt es Zeiten, in denen das Erzwingen eines GC verständlich ist?
  4. Werden Ereignisse vom GC erfasst, wenn das Objekt erfasst wird?
Neal 27.04.2010, 00:09
quelle

5 Antworten

10

Wenn Sie die Komponenten korrekt definiert haben, sollten sie theoretisch nicht erforderlich sein, um Dispose () für Ihre Objekte aufzurufen, da der Finalizer dafür sorgen sollte .

Wenn Sie ein Objekt verwenden, das IDisposable implementiert, ist es empfehlenswert, Dispose () für das Objekt aufzurufen, sobald Sie damit fertig sind.

Für einige Ihrer spezifischen Punkte:

1) Wenn Sie wissen, dass Sie mit dem Formular "fertig" sind, können Sie Dispose () aufrufen. Dies erzwingt eine Bereinigung zu dem Zeitpunkt der nicht verwalteten Ressourcen, die dem Formular zugeordnet sind.

2) In diesem Fall: Wenn Ihr Objekt nur in dieser Methode verwendet wird, verwenden Sie stattdessen "using":

%Vor%

3) Es gibt seltene Gründe, dies zu tun, aber im Allgemeinen, nein.

4) Ereignisse sind ein Delegat - der mit dem Delegaten verknüpfte Speicher wird gesammelt, nachdem der Delegat selbst entwurzelt wurde. Dies geschieht normalerweise, wenn die betreffenden Objekte nicht gelootet werden.

    
Reed Copsey 27.04.2010, 00:12
quelle
3

Sie sollten Dispose auf für jede Klasse aufrufen, die IDisposable implementiert. Wenn es nicht Dispose ed sein müsste, würde es IDisposable nicht implementieren.

Was Ihre anderen Fragen betrifft:

  1. Wenn Sie der% c_de% -Auflistung des Formulars ein Steuerelement hinzufügen, wird das Steuerelement beim Schließen des Formulars automatisch entfernt. Sie müssen also nichts tun.
  2. Wenn das Objekt Controls implementiert, müssen Sie IDisposable aufrufen. Wenn Sie beispielsweise Dispose aufrufen, muss der FileStream entfernt werden, da IDisposable implementiert wird. Ich würde vorschlagen, dass Sie das Konstrukt new FileStream(...) in C # lesen, das die Verarbeitung von using -Objekten erleichtert.
  3. Nicht wirklich, 99,99% der Zeit, wird der Müllsammler wissen, wann die beste Zeit zu laufen ist. Es ist eine von denen, "Sie werden wissen, wann Sie es brauchen" -Situationen.
  4. Wenn das Objekt, das das Ereignis enthält, nicht mehr referenziert wird, werden logische Objektverweise, die im Ereignis enthalten sind, nicht mehr referenziert und können gesammelt werden.
Dean Harding 27.04.2010 00:13
quelle
2

Sehen Sie sich diese Frage an:

Gibt es eine gängige Praxis, wie Sie in .NET den Speicher für Garbage Collector einfacher machen können?

Wenn Ihre Klasse die IDisposable-Schnittstelle instanziiert, bedeutet dies (wahrscheinlich), dass sie über Systemressourcen verfügt, die direkt entsorgt werden müssen. Ein einfacher Weg, dies zu erreichen, ist das using-Schlüsselwort, wie in:

%Vor%

per @Matt S Antwort in dieser Frage, auf die ich verwiesen habe.

Für Ihre Fragen:

  1. Wenn Sie ein Objekt mit IDisposable instanziieren, müssen Sie es beim Schließen des Formulars entfernen. Das ist in WPF schwierig und in Winforms einfach, da Winforms-Dialoge über Dispose-Methoden verfügen. Für WPF habe ich das Problem gelöst, indem ich die WPF-Klasse umgeblättert habe, die als Dispose-Methode bezeichnet wurde, die alle Objekte (wie serielle Ports) entsorgt und dann die WPF-Klasse auf null setzt.
  2. Nein. Lassen Sie den GC sich darum kümmern.
  3. Ich denke schon, aber ich wurde mit negativen Stimmen beleidigt :) Wenn ich sehr große Zuweisungen gemacht habe, ist GC, um sie zu entfernen, eine gute Idee.
  4. Ich bin mir nicht sicher. Ich denke, dass Ereignisse an und für sich Objekte sind, also gesammelt werden, wenn sie nicht mehr benutzt werden.
mmr 27.04.2010 00:12
quelle
1

Wie Reed Copsey sagte, ist es normalerweise nicht notwendig, Dispose anzurufen.

Ein möglicher Fall, der Ihr Problem möglicherweise verursacht, ist, dass ein statisches Objekt Verweise auf andere Objekte enthält, die an keiner anderen Stelle mehr verwendet werden. Der folgende Code zeigt ein Beispiel:

%Vor%

Wenn aus irgendeinem Grund beim Entladen des Formulars die Ereignisverwaltung nicht vom Code aufgehoben wird, wird die Formularinstanz weiterhin vom Statusobjekt referenziert.

    
Codism 27.04.2010 00:32
quelle
0

Wenn Sie ein Objekt IDisposable verwenden, sollten Sie die Anweisung using verwenden, um automatisch mit der Entsorgung für Sie umzugehen.

    
hzap 27.04.2010 00:14
quelle