2009-02-09 2 views
5

Ich weiß, dass Sie Speicherlecks haben, wenn Sie ein Objekt für die angefügten Ereignisse der Maus registrieren. Deshalb müssen Sie WeakEvent pattern verwenden.Wie integrierte WPF-Steuerelemente ihre Ereignishandler für ein angehängtes Ereignis verwalten?

Ich habe ein Problem mit diesem Muster: Wenn Sie es verwenden möchten, können Sie Ihren Handler nicht im XAML-Code definieren.

Für mich bedeutet es, dass jeder Code wie folgt Lecks:

<SomeControl Mouse.MouseDown="MyHandler" /> 

Sofern Sie Ihre Handler explizit im Code entfernen (und ich bezweifle, dass irgendjemand das tut). Jetzt gibt es etwas, was ich nicht verstehe:

<Button Click="MyHandler" /> 

Dieser Code irgendwie irgendwo das Mouse.MouseDown Ereignis verwenden, um einen Klick auf den Button zu erkennen. Mit etwas Forschung mit Reflektor fand ich, dass dieses Ereignis MouseDown der UIElement-Klasse verwendet. Und wenn ich den Code von UIElement lese verstehe ich nicht: Es gibt keinen WeakEventManager!

Kann mir jemand erklären, wie UIElement Ereignisse von Mouse.MouseDown ohne Leck erhalten?

Antwort

7

Die Verwendung normaler Handler in XAML erfordert keine schwachen Referenzen.

Sie erstellen eine Speicherreferenz zwischen dem Hauptsteuerelement und einem untergeordneten Steuerelement, das in diesem Steuerelement enthalten ist. Die Kindersteuerung ist in diesem Fall der Button.

Wenn jemand einen Verweis auf einen Teil des visuellen Baums für das Hauptsteuerelement verwaltet, bleibt der gesamte Baum im Speicher, da er miteinander verknüpft ist (Eltern-/Kindreferenzen).

Wenn nun alle Verweise auf diese Struktur entfernt werden, ist die Ereignisreferenz zwischen Eltern und Kind (das Hauptsteuerelement und die Schaltfläche) nicht von Bedeutung, da diese Steuerelemente bereits über Eltern-/Kindverweise verknüpft waren. Sobald alle externen Referenzen entfernt wurden, kann dieses Steuerelement als Garbage Collected erfasst werden.

Ereignishandler in XAML erstellen nur interne Ereignisreferenzen.

Sie müssen vorsichtig sein, wenn sich externe Clients bei einem Ereignis in einem Steuerelement registrieren, da Sie eine externe Referenz erstellen, die die Steuerung am Leben erhält, solange die Verbindung und der Client vorhanden sind (es sei denn, es handelt sich um eine schwache Referenz) .

Ihre Frage bezieht sich auf angehängte Ereignisse. Es scheint keine klare Dokumentation darüber zu geben, ob angefügte Ereignisse Speicherlecks verursachen. Es sieht für mich so aus, als ob das UI-Steuerelement, das das Ereignis abonniert, Verweise auf das Ereignis enthält und nicht umgekehrt, aber ich nehme an, dass das statische Ereignisobjekt eine Möglichkeit haben muss, das ausgelöste Steuerelement zu benachrichtigen. Es scheint einen überraschenden Mangel an Kommentaren von Microsoft zu geben.

+0

Ich stimme dir zu, aber Handler in XAML zu einem angehängten Ereignis (ich spreche nicht über Steuerelemente Ereignisse, sondern Ereignisse wie Mouse.MouseDown) kann undicht werden, weil es immer einen Verweis darauf gibt. Intern verwenden Button-Klasse Mouse.MouseDown-Ereignisse (UIElement, um spezifisch zu sein). Und ich weiß nicht, warum das nicht leckt. –

+0

Guter Punkt. Angehängte Ereignisse sind externe Referenzen. –

Verwandte Themen