Frage zu eigenen klassenübergreifenden Events

  • VB.NET

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

    egon schrieb:

    "Shared Events" in bestimmten Zusammenhängen die Gefahr von MemoryLeaks bergen. Worauf muss ich achten um mir nicht neue Probleme anzulachen?

    Ist der Event-Konsument kurzlebiger als der Event-Sender, so kann der Garbage-Collector ersteren erst aufräumen, wenn das Event de-abonniert ist.
    Weil der GC räumt alles auf, was per Code nicht mehr erreicht werden kann. Ein Event-Sender erreicht aber noch seine Abonnenten, was sie GC-Tabu macht.
    Ein Shared Event "lebt" die komplette Programm-Laufzeit, und jeder der es abonniert ist solange GC-Tabu.
    Wenn also zB. ein Form ein Shared Event abonniert und nicht deabonniert, so verbleibt es auch nach Schliessen im Speicher.
    Mach das Form 50 mal auf und zu, dann kann sich das allmählich zu einem Problem auswachsen.

    Lösung: Wird das Form (oder ein sonstiger Event-Empfänger) nicht mehr benötigt, so muss es unbedingt das shared Event de-abonnieren.
    Ist kein großer Act - man musses nur wissen, und dran denken.

    Wie gesagt: "in bestimmten Zusammenhängen" - weil wenn das Shared Event nur 2 o. 3 mal abonniert wird, dann ists nur unsauberer Stil, es nicht zu de-abonnieren, wird sich aber nicht merklich auswirken.

    Nochmal wie gesagt: Das Problem tritt nur auf, wenn der Event-Sender länger lebt als sein Konsument.
    Also normal haste zB einen Button auffm Form, der sein Click-Event ans Form sendet. Schliesste jetzt das Form, dann ist der Button weg, und das Form weg, und dann braucht man sich nicht um De-Abonnieren zu kümmern, weil dann sind beide code-unerreichbar, und dann räumt der GC auch beide auf.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ich glaube es spricht nichts dagegen den Global Event gleich wieder in ein Modul einzubauen, mit der entsprechenden Set- und Resetfunktion.
    Ich finde es sieht auch gar nicht so schlecht aus.

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Module GlobalEvent
    4. 'Only for Sub-Methodes
    5. Public Event GEventRaised As GlobalEventDelegate
    6. Public Delegate Sub GlobalEventDelegate(ByVal sender As Object, ByVal typ As String, ByVal msg As String)
    7. Public Sub GEventExecute(ByVal sender As Object, ByVal type As String, ByVal msg As String)
    8. RaiseEvent GEventRaised(sender, type, msg)
    9. End Sub
    10. Public Sub SetGEvent(ByVal ged As GlobalEventDelegate, ByVal _set As Boolean)
    11. If _set Then
    12. AddHandler GEventRaised, ged
    13. Else : RemoveHandler GEventRaised, ged
    14. End If
    15. End Sub
    16. End Module


    VB.NET-Quellcode

    1. Public Sub Main()
    2. 'From Main
    3. Test()
    4. 'From TestClass1
    5. Dim tc1 As New TestClass1
    6. tc1.Test()
    7. 'From TestClass2
    8. Dim tc2 As New TestClass2
    9. tc2.Test()
    10. 'From Form1
    11. CreateForm1()
    12. 'Chain Events
    13. ChainTest()
    14. Console.WriteLine()
    15. Console.WriteLine("FINISH")
    16. Console.ReadLine()
    17. End Sub


    Edit:
    fehlerhaft: "Sub Main" wurde nicht in "GlobalEvent.Module1"

    Ist daraus entstanden, dass ich am Schluss noch den ModuleName geändert habe.
    >> Rechtsklick auf das Projekt und Eigenschaften auswählen und Startprojekt ändern.

    Freundliche Grüsse

    exc-jdbi
    Dateien
    • GlobalEvent.zip

      (12,63 kB, 78 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „exc-jdbi“ ()

    @egon @exc-jdbi hat seinen Post editiert.
    Projekt => Eigenschaften => Anwendung
    Startobjekt,
    dort ModGEvents auswählen.
    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!
    Hallo EDR

    generischen Delegaten = Action(of T)

    Die habe ich mir heute früh Morgens kurz angeschaut. Dann aber nicht weiter verfolgt.
    Heute Abend wenn es mir die Zeit erlaubt, werde ich das weitermachen. Ich kenn die Möglichkeiten noch nicht alle. Arbeite mich aber gerne dort ein.

    Vorallem möchte ich weg von der Shared-Version, sofern möglich. Auch die hier im Beispiel verwendete Funktions-Parameter-Signatur gefällt mir nicht. Das kann man eventuell anders lösen.

    Freundliche Grüsse

    exc-jdbi
    Musste jetzt auch suchen. Ich habs schon länger nicht mehr gelesen. In diesem Artikel beziehst du die generischen Delegaten mit ActionOfT etc. Darum hab ichs auch so verstanden.

    Das obere Beispiel ist umgeschrieben, so ungefähr wie ich es meinte. Von der Funktion her genau gleich. Meines Erachtens die viel bessere Lösung zu globalen Events. EventHandler(Of T As EventArgs) ist ein guter Tip dazu. Danke EDR.


    SharedGlobalEvent

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Module SharedGlobalEvent
    4. Public Event GEventRaised As EventHandler(Of MyEventArgs)
    5. Public Sub GEventExecute(ByVal val As String)
    6. RaiseEvent GEventRaised(Nothing, New MyEventArgs(val, val.GetType.ToString))
    7. End Sub
    8. Public Sub SetGEvent(ByVal ged As EventHandler(Of MyEventArgs), ByVal _set As Boolean)
    9. If _set Then
    10. AddHandler GEventRaised, ged
    11. Else : RemoveHandler GEventRaised, ged
    12. End If
    13. End Sub
    14. End Module
    15. Public Class MyEventArgs
    16. Inherits EventArgs
    17. Public Property Type() As String
    18. Public Property Message() As String
    19. Public Sub New(ByVal msg As String, ByVal typ As String)
    20. Me.Message = msg : Me.Type = typ
    21. End Sub
    22. End Class

    GlobalEvent

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Class GlobalEvent
    4. Public Event GEventRaised As EventHandler(Of MyEventArgs)
    5. Public Sub GEventExecute(ByVal val As String)
    6. RaiseEvent GEventRaised(Me, New MyEventArgs(val, val.GetType.ToString))
    7. End Sub
    8. Public Sub SetGEvent(ByVal ged As EventHandler(Of MyEventArgs), ByVal _set As Boolean)
    9. If _set Then
    10. AddHandler GEventRaised, ged
    11. Else : RemoveHandler GEventRaised, ged
    12. End If
    13. End Sub
    14. End Class
    15. Public Class MyEventArgs
    16. Inherits EventArgs
    17. Public Property Type() As String
    18. Public Property Message() As String
    19. Public Sub New(ByVal msg As String, ByVal typ As String)
    20. Me.Message = msg : Me.Type = typ
    21. End Sub
    22. End Class


    VB.NET-Quellcode

    1. Public Sub Main()
    2. 'From Main
    3. Test()
    4. 'From TestClass1
    5. Dim tc1 As New TestClass1
    6. tc1.Test()
    7. 'From TestClass2
    8. Dim tc2 As New TestClass2
    9. tc2.Test()
    10. 'From Form1
    11. CreateForm1()
    12. 'Chain Events
    13. ChainTest()
    14. Console.WriteLine()
    15. Console.WriteLine("FINISH")
    16. Console.ReadLine()
    17. End Sub



    Edit: Gemäss Post #31



    Freundliche Grüsse

    exc-jdbi
    Dateien
    • GlobalEvent.zip

      (26,33 kB, 76 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Jo, und jetzt den genannten generischen EventHandler auch benutzen (und keinen eigenen Delegaten erfinden)

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Class GlobalEvent
    4. Public Event GEventRaised As EventHandler(Of MyEventArgs)
    5. Public Sub GEventExecute(ByVal val As String)
    6. RaiseEvent GEventRaised(Me, New MyEventArgs(val, val.GetType.ToString))
    7. End Sub
    8. Public Sub SetGEvent(ByVal ged As GlobalEventDelegate, ByVal _set As Boolean)
    9. If _set Then
    10. AddHandler GEventRaised, ged
    11. Else : RemoveHandler GEventRaised, ged
    12. End If
    13. End Sub
    14. End Class
    15. Public Class MyEventArgs
    16. Inherits EventArgs
    17. Public Property Type() As String
    18. Public Property Message() As String
    19. Public Sub New(ByVal msg As String, ByVal typ As String)
    20. Me.Message = msg : Me.Type = typ
    21. End Sub
    22. End Class

    Ups! - Du hast nebenbei von Module auf Class gewechselt. So ist das jetzt kein Shared Event mehr.



    exc-jdbi schrieb:

    In diesem Artikel beziehst du die generischen Delegaten mit ActionOfT etc.
    Darum hab ichs auch so verstanden.
    Ja, in dem Artikel gehe ich vergleichsweise ausführlich auf generische Delegaten ein. Weil das ist eine wichtige Grundlage - um Überhaupt den Begriff "Signatur" zu begreifen.
    Aber nirgends lasse ich vermuten (hoffe ich zumindest), Action(Of T) sei ein akzeptabler Eventhandler.
    Sondern ich erklärs und turns auch brav vor, wie man EventHandler(Of T) einsetzt.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()