it-swarm.com.de

Warum und wie lassen sich Speicherverluste im Event-Handler vermeiden?

Durch das Lesen einiger Fragen und Antworten zu StackOverflow wurde mir gerade klar, dass das Hinzufügen von Ereignishandlern mit += in C # (oder anderen .net-Sprachen) kann zu häufig auftretenden Speicherverlusten führen ...

Ich habe in der Vergangenheit viele Male Ereignishandler wie diesen verwendet und nie bemerkt, dass sie Speicherverluste in meinen Anwendungen verursachen können oder verursacht haben.

Wie funktioniert das (was bedeutet, warum führt das tatsächlich zu einem Speicherverlust)?
Wie kann ich dieses Problem beheben? Benutzt -= genug zum selben Eventhandler?
Gibt es gängige Entwurfsmuster oder Best Practices für den Umgang mit solchen Situationen?
Beispiel: Wie soll ich mit einer Anwendung umgehen, die viele verschiedene Threads hat und viele verschiedene Ereignishandler verwendet, um mehrere Ereignisse auf der Benutzeroberfläche auszulösen?

Gibt es gute und einfache Möglichkeiten, dies in einer bereits erstellten großen Anwendung effizient zu überwachen?

149
gillyb

Die Ursache ist einfach zu erklären: Während ein Ereignishandler abonniert ist, enthält der Herausgeber des Ereignisses einen Verweis auf Abonnent über den Delegaten des Ereignishandlers (vorausgesetzt, der Delegat ist ein Instanzmethode).

Wenn der Herausgeber länger lebt als der Abonnent, bleibt der Abonnent am Leben, auch wenn keine anderen Verweise auf den Abonnenten vorhanden sind.

Wenn Sie sich mit einem gleichen Handler vom Event abmelden, werden der Handler und das mögliche Leck dadurch entfernt. Meiner Erfahrung nach ist dies jedoch selten ein wirkliches Problem - da ich normalerweise feststelle, dass Verleger und Abonnent ohnehin ungefähr die gleiche Lebensdauer haben.

Es ist eine mögliche Ursache ... aber meiner Erfahrung nach ist es ziemlich überfordert. Ihre Laufleistung kann natürlich variieren ... Sie müssen nur vorsichtig sein.

185
Jon Skeet

Ja, -= ist genug, es könnte jedoch schwierig sein, jedes zugewiesene Ereignis im Auge zu behalten. (Einzelheiten finden Sie in Jons Beitrag). Betrachten Sie hinsichtlich des Entwurfsmusters das schwaches Ereignismuster .

12
Femaref

Ein Ereignis ist wirklich eine verknüpfte Liste von Ereignishandlern

Wenn Sie + = new EventHandler für das Ereignis ausführen, spielt es keine Rolle, ob diese bestimmte Funktion zuvor als Listener hinzugefügt wurde. Sie wird einmal pro + = hinzugefügt.

Wenn das Ereignis ausgelöst wird, durchläuft es die verknüpfte Liste Element für Element und ruft alle dieser Liste hinzugefügten Methoden (Ereignishandler) auf. Daher werden die Ereignishandler auch dann aufgerufen, wenn die Seiten nicht mehr so ​​lange ausgeführt werden, wie sie sind sind am Leben (verwurzelt), und sie werden am Leben sein, solange sie angeschlossen sind. Sie werden also solange gerufen, bis der Eventhandler mit einem - = new EventHandler ausgehakt ist.

siehe hier

und MSDN HIER

3
TalentTuner