ThreadPool.QueueUserWorkItem / Tasks() - Warten bis alle Threads beendet

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    ThreadPool.QueueUserWorkItem / Tasks() - Warten bis alle Threads beendet

    Hallo,

    wie kann ich den Programmablauf warten lassen, bis alle Threads aus dem Threadpool beendet sind?

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim myStruct As structInput
    3. For Each row As DataRow In dt.Rows
    4. myStruct = New structInput
    5. ...
    6. Dim w As Threading.WaitCallback = New Threading.WaitCallback(AddressOf bgw_DoWork)
    7. Threading.ThreadPool.QueueUserWorkItem(w, myStruct)
    8. Next
    9. '--> Dieser Code sollte erst ausgeführt werden, wenn alle Threads beendet wurden
    10. '--> Wird aber sofort ausgeführt
    11. End Sub


    --> Ich habe etwas über CountdownEvent gelesen aber ich hab nicht verstanden wie ich es imlementieren kann.

    Einen zweiten Versuch mit TPL habe ich noch versucht:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim myStruct As structInput
    3. Dim taskArray(dt.Rows.Count - 1) As Task
    4. For Each row As DataRow In dt.Rows
    5. myStruct = New structInput
    6. ...
    7. taskArray(i) = Task.Factory.StartNew(Sub() bgw_DoWork(myStruct))
    8. i += 1
    9. Next
    10. Task.WaitAll(taskArray)
    11. '--> Dieser Code sollte erst ausgeführt werden, wenn alle Threads beendet wurden
    12. End Sub


    --> Hier wird zwar gewartet, dafür blockiert währenddessen aber auch die UI !? 8|

    Grüße.
    Hi
    hindert dich irgendwas an der Asynchronität der gesamten Routine? Rufe doch einfach die Methode auf, blockiere bis zum Abschluss die Gui oder so und führe die Aufgabe in einem weiteren Nebenthread aus (womöglich im Threadpool). Schau' dir übrigens auch mal die Parallel-Klasse an.

    Das Problem rührt daher, dass die Gui über eine Nachrichtenschleife arbeitet. Bei jeder Interaktion (Keyboard, Maus, einige Events, wie Textänderung) mit ihr werden Events aufgerufen, in denen auch Benutzercode, wie Button.Click, ausgeführt wird. Jetzt wird die Nachrichtenschleife aber nicht weiter ausgeführt, bis das aktuelle Event abgearbeitet wird und danach geht es (mit Ausnahmen) mit der als nächstes eingereihten Nachricht weiter. Folglich blockiert der Vorgang, wenn er nicht asynchron abgearbeitet wird, da ja auch Maus und Tastatur darauf angewiesen sind.

    Viele Grüße
    ~blaze~
    Bei 1000 Rows machst du 1000 Tasks. Da geht dir der Task mehr in die Performance als die Row selbst. Wie bereits gesagt wurde, wenn du auf einer entsprechenden Framework-Version bist Parallel.For bzw. Parallel.ForEach. Kann man auch über NuGet Paket noch nachziehen.
    Ansonsten die Rows segmentieren und dann eine geringere Anzahl an Segmenten im ThreadPool verarbeiten. Warten bis alles fertig ist, kannste über WaitHandles.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Das sähe übrigens so oder so ähnlich aus:

    VB.NET-Quellcode

    1. 'In Button.Click:
    2. 'Gui einfrieren
    3. Freeze()
    4. 'Womöglich wäre ein eigener Thread aber angemessen, statt ThreadPool.QueueUserWorkItem
    5. System.Threading.ThreadPool.QueueUserWorkItem(Sub(o)
    6. Parallel.ForEach(rows, Sub(row, state, i)
    7. 'Hier die Abarbeitung von row (ist die Row am Index i - i ist ein Long! Ergo ggf. nach Integer konvertieren) durchführen
    8. End Sub)
    9. Me.BeginInvoke(New Action(AddressOf Unfreeze)) 'Gui entfrieren
    10. End Sub
    11. )

    Es gilt noch, Routinen für Freeze und Unfreeze zu implementieren. Dort einfach Enabled, usw. setzen.

    Viele Grüße
    ~blaze~
    @f0x Meinst Du so was:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim tsk() = New Task(9) {}
    3. For i = 0 To 9
    4. Dim tt = New Task(AddressOf bla)
    5. tsk(i) = tt
    6. Next
    7. Task.WaitAll(tsk) ' dies hier
    8. End Sub
    9. Private Sub bla()
    10. ' was tun
    11. End Sub
    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!