IAsyncResult Verständnis Frage

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    IAsyncResult Verständnis Frage

    Hallo Leute ,

    Beschäftige mich gerade mit MultiThreading und komme nicht weiter.
    Wenn ich einen Delegaten Asyncron aufrufen will , kann ich es über die
    IAsyncResult Interface .

    Jetzt ist das aber so das mir die Form trotzdem einfriert.
    Hab ich da was falsch gemacht oder nur falsch verstanden?

    Danke schonmal für eure Antworten :)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim Del As myDel = New myDel(AddressOf MyCallBack)
    3. ListBox1.Items.Add("Vor der Ausführung ")
    4. Dim AsyncRes As IAsyncResult = Del.BeginInvoke(1, Nothing, Nothing)
    5. ListBox1.Items.Add("---------------")
    6. Del.EndInvoke(AsyncRes)
    7. ListBox1.Items.Add("Nach der Ausführung")
    8. End Sub


    VB.NET-Quellcode

    1. Private Sub MyCallBack(X As Integer)
    2. For i As Integer = 0 To X
    3. ListBox1.Invoke(Sub()
    4. ListBox1.Items.Add(X)
    5. End Sub)
    6. Next
    7. End Sub

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

    Ich kann dir nur empfehlen die mit Async Await vertraut zu machen und das darüber zu lösen.
    Dieses Pattern ist sehr simple und übernimmt die Synchronisierung für dich.
    Ganz grob etwa so;

    VB.NET-Quellcode

    1. Public Async Sub Button2_Click(..)
    2. Listbox1.Items.add await SomeProcedureThatReturnsItemsAsync(someParam)
    3. End Sub
    Das ist meine Signatur und sie wird wunderbar sein!
    @Mono

    Mono schrieb:

    Ich kann dir nur empfehlen die mit Async Await vertraut


    Das hab ich auch vor.
    Hab schon gelesen das es besser/einfacher ist mit Async Await.
    Allerdings kann es nicht schaden die anderen Techniken etwas zu verstehn.
    Imo, müsste es ja darauf aufbauen und es einfacher machen wenn man die Basics kennt.

    Amro schrieb:

    die Form trotzdem einfriert.
    Klar, Dein Beispiel leaked.
    Du invokest für jedes Item einzeln sein Add() an die ListBox in den GUI-Thread.
    Das verbrät mehr Performance, als wenn Du das direkt im GUI-Thread machtest.
    Mach Dir mal einen Test, wo Du einen Haufen arithmetische Operationen berechnest und dann lediglich das Resultat im GUI-Thread anzeigst.
    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!
    Wenn ich etwas asynchron laufen lassen will, mache ich dies meist so:

    1. Daten laden und ggf. verarbeiten
    2. Daten anzeigen

    Der erste Schritt erfolgt komplett asynchron. Lediglich am Ende wird dem Benutzer dann ein Ergebnis angezeigt. Das Invoken aus einem separaten Thread heraus kostet immer Zeit, daher muss man sich gut überlegen ob man das macht.

    Im Beispiel des TE wird im Schleifendurchlauf jedes mal Invoked. Da in der Schleife pro Durchlauf kaum Rechenzeit anfällt(hier passiert ja nix rechenintensives), wird der Invoke wohl alle Vorteile der Nebenläufigkeit auffressen. Ich hätte hier in der Schleife eher eine List(OF Integer) asynchron befüllt, das Ergebnis awaited und am ende der Listbox gegeben.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Dank eurer Hilfe hab ich es hinbekommen das die Form jetzt nicht einfriert und der Delagete jetzt Asyncron ausgeführt wird.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim Del As myDel = New myDel(AddressOf MyCallBack)
    3. ListBox1.Items.Add("Vor der Ausführung ")
    4. Dim AsyncRes As IAsyncResult = Del.BeginInvoke(500000000, Nothing, Nothing)
    5. ListBox1.Items.Add("--------------------------------")
    6. 'AsyncRes.AsyncWaitHandle.WaitOne()
    7. 'Del.EndInvoke(AsyncRes)
    8. ListBox1.Items.Add("--------------------------------")
    9. ListBox1.Items.Add("Nach der Ausführung")
    10. End Sub
    11. '
    12. Private Sub MyCallBack(X As Integer)
    13. Dim J = X
    14. For i As Integer = 0 To X
    15. J = J + 1
    16. Next
    17. If ListBox1.InvokeRequired Then
    18. ListBox1.Invoke(Sub()
    19. ListBox1.Items.Add(J)
    20. End Sub)
    21. End If
    22. End Sub


    Meine Erkenntnis ist jetzt :
    Asyncron ist nicht Parallel .
    Asyncron dient nur der Datenverarbeitung im Hintergrund und sollte nur nach Beendigung an den Benutzer oder dem Control zurückgegeben werden. (Delegaten und IAsyncRes / sprich CallBack)
    Für Parallele verarbeitung einen Thread oder Task nehmen.
    Korregiert mich bitte wenn ich es nicht richtig verstanden hab.
    Ist an den Code noch was zu verbessern oder kann man so darauf aufbauen wenn man einen Delegaten Asyncron aufrufen will.
    Ich würde eher sagen:
    Asynchron ist das neue Parallel!
    Denn gerade die Tasks basieren darauf, dass Aufgaben zunächst Konkurrent im selben Thread ausgeführt werden, sodass auf der einen Seite nichts durch Invoke() blockiert wird, auf der anderen Seite die Ressourcen für einen extra Thread nicht aufgewendet werden müssen.

    Darüber hinaus verbergen Tasks, die in Verbindung mit async/await benutzt werden, das ganze komplexe Threading im Hintergrund, während "Asynchronität", bei richtigem Gebrauch, immer Gewährleistet ist, und der Code dabei noch überaus anschaulich wird, im vergleich zu jedem anderen bisherigen Threading/Async Pattern.
    Das ganze Thema ist echt verwirrend.
    Mal geht es um Threads mal um Tasks, dann wieder irgendwelche Delegates und Asyncron.
    Dann kommt async await und wieder Threadpool.
    Wie habt ihr euch da eingearbeitet?
    Ich möchte das ganze schon verstehen, weil ich der Meinung bin das es für Datenverarbeitung,
    gerade mit Datenbank, sehr interessant ist.
    Könnt Ihr mir da mal einen Schubser geben.
    Das .NET Framework hatte in seiner Laufzeit verschiedene Möglichkeiten gehabt, Multithreading bzw. "asynchronität" oder "parallelität" zu realisieren. Ob nun Threads selbst, Thredpool, BeginMethod/EndMethod, Tasks, async/await, alles war/ist zu seiner Zeit das Beste gewesen, was man hat bekommen können. Zurzeit ist es nunmal Tasks mit async/await, und nicht das worin du dich im Moment versuchst einzuarbeiten.

    Tasks musst du dir als Untereinheit von Threads vorstellen. Ein Thread kann mehrere Tasks beherbergen, die Konkurrent ausgeführt werden. Das bedeutet, dass von der CPU-Zeit, die der Thread bekommt, diese Tasks jene unter sich aufteilen. Wie genau entscheidet die CLR bzw. das OS, und interessiert uns auch nicht wirklich. Sollte ein Task nun jedoch vermehrt CPU-Zeit in Anspruch nehmen, so kann die CLR bzw. das OS nun diesen Task in einen anderen/neuen Thread auslagern, sodass die Aufgabe schneller ausgeführt werden kann. Ist der Task erledigt, bringt die CLR den Task wieder zurück in den Ursprungsthread, und man kann, ohne Invoke. o.Ä., auf das Ergebnis zugreifen.
    Hallo @Amro

    Ich denke das könnte dich interessieren.

    Aber schon witzig. @Mono hat bereits in der ersten Antwort in Post #2 darauf hingewiesen. ;)

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##