Remove all Handlers

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Remove all Handlers

    In meiner großen WinForms Anwendung werden in Fenster im Init Standard Tastaturhandler hinzugefügt und in der Statuszeile eines neuen Fenster bestimmte Buttons mit Diversen Events MouseOver, Click usw. je nach Status hinzugefügt.

    Bisher habe ich die per AddHandler hinzugefügten Events jedoch nicht entfernt. Wenn die Anwendung nun sehr lange läuft ( > 24 h) kommt es zu einem MemoryOut Fehler.

    Nun möchte ich das beseitigen. Es wäre sehr praktisch, wenn ich ich eine Funktion finden würde, die alle zur Laufzeit hinzugefügten Handler auch wieder mit RemoveHandle entfernen könnte.

    Hinzugefügte Controls beseitige ich derzeit beim Fenster schließen wie folgt:

    VB.NET-Quellcode

    1. While panDoku.Controls.Count > 0
    2. panDoku.Controls(0).Dispose()
    3. End While


    Gibt es für die Handler jedes einzelnen Controls auch eine Auflistung?

    Der flotte Johann schrieb:

    Gibt es für die Handler jedes einzelnen Controls auch eine Auflistung?
    Nein.
    Du kannst aber mit AddHandler ... und RemoveHandler ... statt ... Handles ... XDein Ziel erreichen:
    learn.microsoft.com/de-de/dotn…ents/addhandler-statement
    learn.microsoft.com/de-de/dotn…s/removehandler-statement
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Du kannst aber mit AddHandler ... und RemoveHandler ... statt ... Handles ... XDein Ziel erreichen
    ?( Das ist doch schon gegeben:

    Der flotte Johann schrieb:

    Bisher habe ich die per AddHandler hinzugefügten Events jedoch nicht entfernt.


    @Der flotte Johann: Konntest Du sicherstellen, dass die Exception aufgrund von fehlenden RemoveHandler-Anweisungen kommt?
    Werden im Laufe der Zeit immer mehr EventHandler automatisch verlinkt? Das konnte ich jetzt nicht rauslesen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Nein, ich kann nicht sicherstellen, dass der Speicherfehler wirklich an den fehlenden RemoveHandler Anweisungen liegt.

    Im Laufe der Zeit (bei jedem Öffnen eines Fensters) werden in die Fußzeile des Fensters Buttons (ca. 3 Stück) und Labels (1-2 Stück) eingefügt.
    Das ist je Fenster verschieden.

    Insgesamt hat die Anwendung (ERP) mehr als 100 verschiedene Fenster und um das Erscheinungsbild gleich zu halten werden in der Fußzeile (Panel) jedes Fensters bestimmte Standardbuttons eingefügt.
    Hilfe, Print, Export .

    Nachdem es öfters MemoryFehler gegeben habe, habe ich mir die

    VB.NET-Quellcode

    1. GetGuiResources(Process.GetCurrentProcess().Handle, 1)

    angesehen, diese Zahl steigt kontinuierlich nach oben. Pro geöffneten und geschlossenen Fenster sind es ca. 6 Stück

    Es gibt aber auch sehr komplexe Fenster bei denen mal 60 Stück verbraucht werden.
    Was spräche dagegen, diese bereits im Designer auf's Form zu packen?
    btw: Sind diese wiederkehrenden Controls in einen UserControl untergebracht? Das verringert zwar die Anzahl der EventHandler nicht, macht aber das Hinzufügen leichter.

    Und um die Frage zu beantworten: Es gibt das Gewünschte von Haus aus nicht, man kann sich aber sowas basteln. Ich hatte das mal gemacht, funktioniert immer noch ganz gut. Ich kram es nachher mal raus und poste es hier.

    ##########

    @Der flotte Johann: Bevor Du weitermachst: Ich habe jetzt mal versucht, das nachzubasteln. GetGuiResources gibt für mein MainForm 28 zurück. Auf Knopfdruck wird ein neues SubForm erstellt, darauf ein Label und dessen ClickEvent wird per Addhandler an eine Methode gebunden. Mit GetGuiResources steigt die Zahl der UserGuiObjects - wie erwartet, in dem Fall auf 33*. Aber wenn ich das Fenster schließe, ist der Wert wie vorher bei 28! Also gibt entweder GetGuiResources keine relevante Messzahl wieder oder es liegt nicht an dem Szenario!

    * Und zwar egal, ob ich Event und EventHandler mit AddHandler verknüpfe oder keine Verknüpfung erstelle.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „VaporiZed“ ()

    Klar, könnte man das mit dem Designer tun.
    Da geht es aber um Konsitenz und bequemlichkeit. Die Buttons sollten dann auch auf allen 100 Fenster immer an der richtigen Position und mit den richtigen Eigenschaften erscheinen.
    (Hilfebutton hat ein Image, der Druckbutton auch).
    Evtl. muss zukünftig allen Formen, die aus dem Bereich Auftragsbearbeitung kommen noch eine weiteres Element hinzugefügt werden.... und so was halt, was jetzt mit einer einzigen InitForm abgeklärt wird.

    Von daher wäre die Variante über ein UserControl sicher ganz nett.
    Dazu müsste man dann mal gerade 100 Fenster anpassen und den Designer stapazieren. Machbar wäre das.

    Nebenfrage: Muss ich beim UserControl auch alle händisch hinzugefügten Handler (Click, MouseEnter, MouseOver.,,,,) wieder selber entfernen- oder machts das VB selbst???

    Ich habe mir auch schon überlegt, beim Addhandler eine Liste zu füllen und die dann beim FormClose oder Closing??? durchzugehen und die Handler zu removen.
    Wie geschrieben: Automatisch geht da nix und ob die AddHandler wirklich für die Exception verantwortlich sind, soltlest Du definitiv erstmal herausfinden. Vielleicht indem Du per Timer in kurzer Zeit immer wieder Fenster öffnest und schließt. Denn wenn Du das EventHandling-Problem jetzt aufwendig löst, aber das Memory-Problem trotzdem bleibt, hast Du wohl nix gewonnen.
    Hier mal meine Variante zum Auf- und Abbau von dynamisch erzeugten Event-EventHandler-Verdrahtungen:
    EventPack

    VB.NET-Quellcode

    1. Public Class EventPack
    2. Property EventRaiser As Object
    3. Property EventName As String
    4. Property EventHandlerName As String
    5. Property EventHandler As [Delegate]
    6. Property IsActive As Boolean
    7. Public Sub New(EventRaiser As Object, EventName As String, EventHandlerName As String, EventHandler As [Delegate])
    8. Me.EventRaiser = EventRaiser
    9. Me.EventName = EventName
    10. Me.EventHandlerName = EventHandlerName
    11. Me.EventHandler = EventHandler
    12. Me.IsActive = False
    13. End Sub
    14. End Class


    EventPackList

    VB.NET-Quellcode

    1. Public Class EventPackList : Inherits List(Of EventPack)
    2. Sub AddNewEventHandlerTo(EventRaiser As Object, ObjectWhichContainsTheEventHandler As Object, EventName As String, EventHandlerName As String)
    3. If Not EventIsNew(EventRaiser, EventName) Then Return
    4. AddEventHandlerTo(EventRaiser, ObjectWhichContainsTheEventHandler, EventName, EventHandlerName)
    5. End Sub
    6. Private Function EventIsNew(EventRaiser As Object, EventName As String) As Boolean
    7. Return Not Any(Function(x) x.EventRaiser Is EventRaiser AndAlso x.EventName = EventName)
    8. End Function
    9. Private Sub AddEventHandlerTo(EventRaiser As Object, ObjectWhichContainsTheEventHandler As Object, EventName As String, EventHandlerName As String)
    10. Dim NewEventPack = New EventPack(EventRaiser, EventName, EventHandlerName, Nothing)
    11. Add(NewEventPack)
    12. Dim EventInfo = EventRaiser.GetType.GetEvent(EventName)
    13. Dim EventHandler = [Delegate].CreateDelegate(EventInfo.EventHandlerType, ObjectWhichContainsTheEventHandler, EventHandlerName)
    14. NewEventPack.EventHandler = EventHandler
    15. End Sub
    16. Public Sub ActivateAllEventHandlers()
    17. Me.Where(Function(x) Not x.IsActive).ToList.ForEach(Sub(x) ActivateEventHandler(x))
    18. End Sub
    19. Public Sub DeactivateAllEventHandlers()
    20. Me.Where(Function(x) x.IsActive).ToList.ForEach(Sub(EventPack) DeactivateEventHandler(EventPack))
    21. End Sub
    22. Private Sub ActivateEventHandler(EventPack As EventPack)
    23. Dim EventInfo = EventPack.EventRaiser.GetType.GetEvent(EventPack.EventName)
    24. EventInfo.AddEventHandler(EventPack.EventRaiser, EventPack.EventHandler)
    25. EventPack.IsActive = True
    26. End Sub
    27. Private Sub DeactivateEventHandler(EventPack As EventPack)
    28. Dim EventInfo = EventPack.EventRaiser.GetType.GetEvent(EventPack.EventName)
    29. EventInfo.RemoveEventHandler(EventPack.EventRaiser, EventPack.EventHandler)
    30. EventPack.IsActive = False
    31. End Sub
    32. End Class


    Beispiel

    VB.NET-Quellcode

    1. Friend Class Form1
    2. Private ReadOnly EventPacks As New EventPackList
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. EventPacks.AddNewEventHandlerTo(Button2, Me, "MouseClick", NameOf(Button2_MouseClick)) 'Event-EventHandler-Verdrahtung registrieren
    5. EventPacks.AddNewEventHandlerTo(Label1, Me, "Click", NameOf(Label1_Click))
    6. EventPacks.ActivateAllEventHandlers() 'alle aktivieren
    7. End Sub
    8. Private Sub Label1_Click(sender As Object, e As EventArgs)
    9. Button2.BackColor = If(Button2.BackColor = Color.Red, Color.Green, Color.Red)
    10. End Sub
    11. Private Sub Button2_MouseClick(sender As Object, e As MouseEventArgs)
    12. Label1.Top += 5
    13. End Sub
    14. Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    15. EventPacks.DeactivateAllEventHandlers() 'alle deaktivieren; alternativ z.B. im FormClosing-EventHandler
    16. End Sub
    17. End Class

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Esrt mal vielen Dank!!!

    Dann kümmere ich mich mal darum den Fehler per Schleife zu provozieren.


    Es liegt nicht an den Addhandler / RemoveHandler.
    Die Handles müssen woanders kleben bleiben. Es ist in einem meiner UserControls, so viel steht schon mal fest.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Der flotte Johann“ ()