2008-11-18 13 views
155

Wenn ich den folgenden Code:Führen Ereignishandler die Garbage Collection nicht aus?

MyClass pClass = new MyClass(); 
pClass.MyEvent += MyFunction; 
pClass = null; 

Will pClass sein Müll gesammelt? Oder wird es herumhängen und immer noch seine Ereignisse feuern, wenn sie auftreten? Muss ich Folgendes tun, um die Speicherbereinigung zu ermöglichen?

MyClass pClass = new MyClass(); 
pClass.MyEvent += MyFunction; 
pClass.MyEvent -= MyFunction; 
pClass = null; 
+9

Ich werde versuchsweise Lesern, die an dieser Frage interessiert sind, empfehlen, sich mit leichten Ereignissen/schwachen Ereignismustern vertraut zu machen, die NICHT verhindern, dass die Garbage Collection stattfindet. Ein gutes SO Bootstrap zu diesem Thema ist http://stackoverflow.com/questions/185931/weakreference-and-event-handling – fostandy

+13

Hinweis für die Nachwelt: Einstellung der Verweis auf Null verzögert einfach den Garbage Collector durch eine Erweiterung um eine Zeile den Umfang von die Referenz. .NET ist nicht VB6. –

Antwort

172

Für die spezifische Frage „Wird pClass Müll gesammelt werden“: Das Ereignis Abonnement hat keine Auswirkung auf die Sammlung von pClass (als Herausgeber).

Für GC im Allgemeinen (insbesondere das Ziel): es hängt davon ab, ob MyFunction statisch oder instanzbasiert ist.

Ein Delegat (z. B. eine Ereignissubskription) für eine Instanzmethode enthält einen Verweis auf die Instanz. Also ja, ein Event-Abonnement wird GC verhindern. Sobald jedoch das Objekt, das das Ereignis (pClass oben) veröffentlicht, für die Sammlung in Frage kommt, ist dies kein Problem mehr.

Beachten Sie, dass dies in eine Richtung ist; das heißt, wenn wir haben:

publisher.SomeEvent += target.SomeHandler; 

dann „Publisher“ halten „Ziel“ am Leben, aber „Ziel“ nicht halten „Verlag“ am Leben.

Also nein: Wenn pClass trotzdem gesammelt wird, müssen Sie die Listener nicht abmelden. Wenn pClass jedoch langlebig war (länger als die Instanz mit MyFunction), konnte pClass diese Instanz am Leben erhalten, so dass erforderlich wäre, um sich abzumelden, wenn das Ziel erfasst werden soll.

Statische Ereignisse sind jedoch aus diesem Grund sehr gefährlich, wenn sie mit instanzbasierten Handlern verwendet werden.

+0

Danke, das habe ich vermutet. –

+5

Nun, wenn die Frage ist, wird pClass Müll gesammelt sein, dann ist die Antwort "es hängt ob ..." nicht wirklich richtig. Es kommt nicht darauf an, wie Marc selbst weiter unten feststellt. –

+0

@Tor - fair genug - ich werde klären –

5

Ja, pClass wird Müll gesammelt werden. Das Ereignis-Abonnement bedeutet nicht, dass ein Verweis auf pClass existiert.

Ein so nein, Sie müssen den Handler nicht trennen, damit pClass Müll gesammelt wird.

6

Sobald ein Stück Speicher nicht mehr referenziert wird, wird es ein Kandidat für die Garbage Collection. Wenn die Instanz Ihrer Klasse den Gültigkeitsbereich verlässt, wird sie von Ihrem Programm nicht mehr referenziert. Es wird nicht mehr benutzt und kann daher sicher gesammelt werden.

Wenn Sie nicht sicher sind, ob etwas gesammelt wird, stellen Sie sich die folgende Frage: Gibt es noch einen Hinweis darauf? Die Ereignishandler werden von der Objektinstanz referenziert, nicht umgekehrt.

0

pClass wird Müll gesammelt werden. Wenn sich das obige Code-Snippet jedoch in einer anderen Klasse befindet, wird die Instanz dieser Klasse möglicherweise nicht gelöscht, wenn Sie pClass nicht auf null setzen.