[Events] List(of EventHandler) = Nothing, nach einer Initialisierung, mit new List(of EventHandler)

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

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

    [Events] List(of EventHandler) = Nothing, nach einer Initialisierung, mit new List(of EventHandler)

    Hallo,

    ich arbeite zwischendurch an ein paar Projekten, um mich selbst in vb.net zu verbessern und zu lernen.
    Ich hab ein bisschen mit 'Custom Event' und 'EventHandler' gearbeitet und wollte dadurch ein 'Invoke' erreichen, damit das Event auf dem Main UI-Thread ausgeführt wird.

    VB.NET-Quellcode

    1. Private List_PhaseOutRequestTimedOut As List(Of EventHandler) = New List(Of EventHandler)
    2. Custom Event PhaseOutRequestTimedOut As EventHandler
    3. AddHandler(ByVal NewHandler As EventHandler)
    4. List_PhaseOutRequestTimedOut.Add(NewHandler)
    5. End AddHandler
    6. RemoveHandler(ByVal Handler As EventHandler)
    7. List_PhaseOutRequestTimedOut.Remove(Handler)
    8. End RemoveHandler
    9. RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
    10. For Each Handler In List_PhaseOutRequestTimedOut
    11. Handler.BeginInvoke(sender, e, New AsyncCallback(AddressOf EndAsync), Nothing)
    12. Next
    13. End RaiseEvent
    14. End Event


    Hier der Code, wie er in einer meiner Klassen steht.
    Das Event 'PhaseOutRequestTimedOut' soll von einem separaten Thread aufgerufen werden (Raised), damit es in meiner Hauptform "empfangen" werden kann.

    Jedoch wird beim hinzufügen eines EventHandlers (in Zeile 5) immer ein fehler zurückgegeben: NullReferenceException.
    Verwiesen wird auf die Zeile 5: List_PhaseOutRequestTimedOut.Add(NewHandler)
    Das Objekt 'List_PhaseOutRequestTimedOut' ist = 'Nothing'.

    Aber warum? Ich hab es doch initialisiert?

    Zur Info, die Variable steht mitten in der Klasse, also nicht ganz am Anfang. Ich dachte das wäre ok - ist es das?

    Falls ihr mehr Infos oder Code braucht, gerne.
    Vielen Dank erstmal für die Hilfe.
    Dateien
    • LoopThreader.zip

      (327,98 kB, 139 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „BigDaddy“ ()

    wow...

    Wenn ich die Variable "manuell" im Sub New() initialisiere und das Event über AddHandler (nach der Initialisierung der Variable) auf die Methode "zeigen" lasse, dann kommt diese Fehlermeldung nicht mehr.

    Wie kann ich jetzt erreichen, dass die Variable vor dem Event-AddHandler initialisiert wird?
    Dein Code - wenn er täte, macht das gegenteil vin dem, wasser soll: Er transferiert den Aufruf in einen Nebenthread (und ganz bestimmt nicht in den Gui-Thread)

    Ansonsten sieht das gezeigte ok aus, daher vermute ich, es liegt am Nicht-Gezeigten, Fehler beim Umgang mit Threads ist mein Hauptverdächtiger. Genauer weissichs nicht, da kann man sehr viel falsch machen, und kommt man immer besonders schwierig drauf.

    Wenn du dein Projekt verzippen kannst, dass ich den Fehler reproduzieren kann... - allerdings probier den Zip vorher aus, dass er auch wirklich geht.
    Hab schon gemerkt, dass die Events nicht zum Aufruf in den Gui-Thread transferiert werden || #ThreadübergreifenderVorgang

    LoopThreader.zip (Habs mal hochgeladen)

    VB.NET-Quellcode

    1. If IsNothing(List_PhaseOutRequestTimedOut) = True Then
    2. List_PhaseOutRequestTimedOut = New List(Of EventHandler) ' Sicherstellen, dass die Liste initialisiert ist.
    3. End If


    in der Klasse LoopThreader.vb, Zeile 64-66 verhindert aktuell noch den Fehler. Aber find' ich irgendwie nicht so cool, dass da stehen zu haben.
    Auch wenn es funktioniert...

    Allerdings werden die Events nicht im Gui-Thread ausgelöst. Gibt es da eine Möglichkeit das zu machen?
    Ich vermute mal, über Control.Invoke? ?(
    Welcher Verweis wäre da der Beste? Oder einfach irgendeine Form nehmen?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „BigDaddy“ ()

    Ui - jetzt kommt ziemlich viel auf dich zu - näm,ich 7 tw. sehr verschiedene Themen.
    Das ist immer problematisch, denn wenn ich multithematische Antworten gebe fassen die Leuts immer nur ein Thema auf - meist das absolut unwichtigste.
    Und dann bin ich beleidigt, weil ich was ausarbeite, und kriege ühaupt kein Feedback.
    Also hiermit Bitte um Feedback zu 7 Themen - und bitte nicht: "bielen Dank, schau ich mir später an".
    Und lass uns mittm ersten anfangen, das ist nämlich das wichtigste.



    1)
    Was du dringend machen musst ist Visual Studio - Empfohlene Einstellungen



    2)
    IsNothing ist bestandteil des vb6-Rotzes, von dem man sich fernhalten sollte, wenn man das proggen wirklich lernen möchte - siehe punkt #1



    3)
    Zur Frage: zum BeginInvoken nicht irgendeine Form nehmen, sondern MyApplication.OpenForms(0).
    Diese Form ist immer da (sonst ist die Anwendung ja geschlossen) - und ist natürlich immer im Gui-Thread.



    4)
    Ansonsten ist dein Programm imo kein gutes Anfänger-Thema.
    Und Nebenlaäufigkeit mittm GUI synchronisiert man heutzutage mittm Async-Aweit-Pattern



    5)
    Und nebenbei: Es ist Unsinn, einen Boolean-Ausdruck mit True zu vergleichen - da kann nix neues bei rauskommen - gugge: Boolean, Vergleiche und bedingte Verzweigungen



    6)
    Ach und nochwas: Von so verlorenen Zeilen SchnipselCode kann man kaum sinnvoll was ablesen (ausser eher so triviale Anfänger-Fehler).
    Wenn Code posten - dann möglichst immer eine ganze Methode - mindestens der Methoden-Kopf sollte unbedingt dabei sein.



    7)
    Und nochwas: Code hochladen bitte mit VBParadise - keine SchmuddelHoster.
    Gugge

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

    Danke erstmal für deine schnellen und ausführlichen Antworten. Hab ich sonst noch nie in einem Forum entdeckt. :love:
    Mir ist bewusst, dass ich recht gutes Potential zum programmieren habe und ich lerne gerne.
    Darum immer her mit konstruktiver Kritik! :thumbsup:




    1) Klar soweit! 8-) Ich hatte sowieso etwas gegen imports




    2) If variable Is Nothing Then der Is-Operator vergleicht die Referenzen beider Objekte, ob diese auf das selbe Objekt zeigen? Hoffe hab das richtig geschluckt ?(




    7) Das ist mein Root-Server. Willst du mich als Schmuddelig bezeichnen? ^^




    Ich versuch das alles mal umzusetzen!
    Ich weiß allerdings nicht, was Sync und Async ist und wozu es bei Threads dient. Gibts da irgendwo eine hübsche erklärung? :)




    VB.NET-Quellcode

    1. My.Application.OpenForms.Item(0).BeginInvoke(Handler, New Object() {sender, e})


    .. hat super funktioniert! 8o




    Allerdings frage ich mich, warum Private List_PhaseOutRequestTimedOut As List(Of EventHandler) erst nach der Registrierung des ersten EventHandlers in der LoopThreader-Klasse initialisiert wird...

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

    2) jepp
    7) nein natürlich nicht! ;) Ich klicks aber auch nicht auf iwelche Links, die Schmuddelhoster sein könnten.
    ...

    BigDaddy schrieb:

    Allerdings frage ich mich, warum Private List_PhaseOutRequestTimedOut As List(Of EventHandler) erst nach der Registrierung des ersten EventHandlers in der LoopThreader-Klasse initialisiert wird...
    Wohl weil sie vorher nicht gebraucht wird.
    Bist du übrigens sicher? Eiglich sollte sie initialisieren, wenn das sie enthaltende Objekt ertellt wird - mit New

    Es heißt Async/Await - Sync hast du dir ausgedacht, wohl um dich selbst zu verwirren ;)
    Hier ein Tut - du solltest aber mit generischen Delegaten und anonymen Methoden soweit klarkommen - sonst wirst du das nicht so einfach finden (wie's eiglich ist).
    codeproject.com/Articles/10296…ithout-any-additional-Lin

    Und hier noch ein Plan für Selbst-Lerner: Datenverarbeitungs-Vorraussetzungen
    Das scheint evtl. zu 80% an deim jetzigen Thema vorbei, aber glaub mir: Wenn du iwann mal was fertig kriegen willst, musst du ungefähr alles davon umgesetzt/gelernt haben.

    ErfinderDesRades schrieb:

    BigDaddy schrieb:

    Allerdings frage ich mich, warum Private List_PhaseOutRequestTimedOut As List(Of EventHandler) erst nach der Registrierung des ersten EventHandlers in der LoopThreader-Klasse initialisiert wird...
    Wohl weil sie vorher nicht gebraucht wird.
    Bist du übrigens sicher? Eiglich sollte sie initialisieren, wenn das sie enthaltende Objekt ertellt wird - mit New


    Wenn ich

    VB.NET-Quellcode

    1. If IsNothing(List_PhaseOutRequestTimedOut) = True Then
    2. List_PhaseOutRequestTimedOut = New List(Of EventHandler) ' Sicherstellen, dass die Liste initialisiert ist.
    3. End If

    in Zeile 64-66 entferne/auskommentiere, bekomme ich in Zeile 67 eine NullReferenceException, weil das Objekt Nothing ist.
    Und wenn ich Handles Me.PhaseOutRequestTimedOut hinter dem Methodenkopf in Zeile 47 entferne, bekomme ich diesen Fehler nicht mehr.

    Soweit ich jetzt richtig schlussfolgere, wird das Event durch Handles Me.PhaseOutRequestTimedOut in Zeile 47 vor der Initialisierung der Variable registriert und somit auf eine nicht-initialisierte Variable zugegriffen.
    Und ich weiß nicht, wie ich das verhindern soll...

    Muss ich das Event der Methode manuell durch AddHandler im Sub New() hinzufügen? (Nachdem ich die Variable manuell in Sub New() initialisiert habe)
    Oder gibt es eine andere Möglichkeit?

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

    Den Code, den du besprichst, sehe ich nicht.
    Grundsätzlich ist AddHandler imme eine Alternative zur Handles-Klausel.
    Ob das in diesem Fall die Rettung bringt, bzw ob die Rettung nicht noch einfacher zu haben wäre - naja - ich guckma in dein Upload.

    Und da sehe ich als erstes: Option Strict ist leider Off, und der Deppen-GeneralImport ist leider drinne.

    Also da warte ich nu, bis du das in Ordnung gebracht hast, weil Strict-Off - Deppen-Namespace-Code ist nicht wert, sich mit zu beschäftigen.
    Oder weniger wertend formuliert: Es ist inefizient, in solchem Code auf Fehlersuche zu gehen, aufgrund der Mengen an verborgenen Fehlern, die zu erwarten sind.
    Visual Studio - Empfohlene Einstellungen

    Ach und nochwas sehe ich: VS2010. In dieser Version ist Async/Await leider noch nicht verfügbar - damit brauchste dich also nicht zu "belasten".

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

    Microsoft Visual Studio 2010 hat sich wohl nicht dafür interessiert das Projekt ordentlich abzuspeichern.
    Wenn ich das Projekt nach 2017 kopiere und dort öffne, bekomme ich eine ältere Version vorgelegt. Eine Version, wo im Namespace My.Libraries.Threading noch zig Klassen sind...
    Ich hab im aktuellen Projekt nur drei Klassen im Namespace My.Libraries.Threading liegen.

    Hab das aktuelle Projekt mal hochgeladen... (Strict On, kein Microsoft.VisualBasic-Import, aus Visual Studio 2017)
    Dateien
    • LoopThreader.zip

      (311,82 kB, 133 mal heruntergeladen, zuletzt: )

    BigDaddy schrieb:

    aus Visual Studio 2017
    Ist es nicht.
    Guck dir die .sln-File im Editor an:

    Quellcode

    1. Microsoft Visual Studio Solution File, Format Version 11.00
    2. # Visual Studio 2010
    3. Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "LoopThreader", "LoopThreader\LoopThreader.vbproj", "{393CDF55-641F-4145-B2EF-4CCD525C16AB}"
    4. EndProject
    5. ...
    Ansonsten ist mir ganz unklar was das Gedöhns eigentlich soll - ich glaub 80% davon kann weg.
    Welches Ziel soll dein Proggi erreichen?