Click here to Skip to main content
15,917,062 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

using the following code, which is basically identical with a MS example, my UI freezes if I uncomment the "Task.WaitAll" line. Shouldn't the threads be processed independently in the background? Or is the wait command in a wrong place?

Thank you for advice,
Michael

What I have tried:

Try
    Dim tasks As New List(Of Task)()

    For Each drv In drives
        Dim currentDrive As Drive = drv
        If drv.IsReady Then
            Dim readTask As New Task(Sub()
                                         queryDrive(currentDrive)
                                     End Sub, TaskCreationOptions.LongRunning)
            tasks.Add(readTask)
            readTask.Start()
        End If
    Next

    'Task.WaitAll(tasks.ToArray())

    timerTotalMsStopwatch.Stop()
    btnGetComputers.Enabled = True
    btnCancel.Enabled = False

    Dim msg As String = String.Format("{0} files ({1:0} Sec).", files.Count, timerTotalMsStopwatch.ElapsedMilliseconds / 1000)
    SetUIText(msg, msg & vbCrLf)

Catch ex As Exception
    MsgBox(String.Format("{0}", ex.StackTrace), MsgBoxStyle.Critical, "Error")

End Try
Posted
Updated 12-Feb-19 6:15am
Comments
Maciej Los 9-Feb-19 14:25pm    
No, it's not identical with a MS example. I do not see even similar solution in MSDN documentation. As far as i remember, i've provided you in the answer to your previous question several links.
Sonhospa 9-Feb-19 16:49pm    
Hi again, yes you did and I looked at them - trying to not get even more confused. Please understand that I'm new to this topic! Here's the MS example I mentioned (sorry I don't find how to insert this in a better way: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.-ctor?view=netframework-4.7.2). They don't run into the same problem as they output to the console after every task is finished.

The WaitAll is a blocking call. The UI thread won't do anything else until all of the Tasks complete, thereby satisfying the condition WaitAll is looking for.

If you're looking to time this operation, you would probably be better served by creating a method that the tasks Invoke on the UI thread to remove the Tasks from the tasks list and when the list reaches a Count of 0, then you can stop the timer and enable/disable buttons.
 
Share this answer
 
Comments
Sonhospa 9-Feb-19 14:29pm    
Hello Dave, thank you for having a look. I don't understand what you mean. Having the long running tasks on the UI thread would freeze the UI as well, or not? Sorry, it's a bit complicated for my brain...
Dave Kreskowiak 9-Feb-19 14:36pm    
The Tasks you started are not on the UI thread. They are not hanging up the UI at all. It's the call to WaitAll that's doing it.

It's not a matter of placing WaitAll in the correct place. It's a matter of not using it at all!
Sonhospa 9-Feb-19 14:41pm    
Yes, that I understand. I mean how could I achieve to have my "summary" (counts and duration) on the UI thread, i.e. after the threads are all finished? From what I read, the Task.WaitAll is exactly for that purpose... or did I misunderstand that?
Dave Kreskowiak 9-Feb-19 14:48pm    
If you want to hang your UI for the time the Tasks are running, use WaitAll. It's a blocking call, which means no other code on the thread WaitAll is called on will run until it returns. If you call WaitAll on the UI thread (the thread your app starts on), the UI will do nothing at all until WaitAll returns and the app returns to an idle state. This will allow the message pump on the UI thread to run and process messages, lick mouse clicks and paint messages.

If you don't want to hang your UI, you're going to have to get really creative and NOT use any of the Wait methods.
Sonhospa 9-Feb-19 15:07pm    
I mean how could I achieve to have my "summary" (counts and duration) on the UI thread, i.e. after the threads are all finished? I deleted Wait already, but "you have to get really creative" I didn't expect as advice and possible solution in this forum. Thank you though.
As Dave already explained, WaitAll is a blocking call which will prevent your UI thread from doing anything until all of the tasks have completed.

The simplest solution is to make your method Async, and use:
VB.NET
Await Task.WhenAll(tasks)
instead of the Task.WaitAll(...) line.

Asynchronous Programming with Async and Await (Visual Basic) | Microsoft Docs[^]
How to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic) | Microsoft Docs[^]
 
Share this answer
 
Comments
Maciej Los 12-Feb-19 14:43pm    
5ed!
Sonhospa 13-Feb-19 13:24pm    
Thank you very much, Richard! After studying different sources for the last weekend, I found exactly this method, tried it and - voilá it works!

Since I'm not a professional programmer, it was also critical for me, where exactly in my code I had to place it. You didn't mention that, but I would have understood implicitly to just change my old line. In addition, following another hint, I inserted "readTask.GetAwaiter()" before "readTask.Start()".

Thank you though, and since it's the 'missing piece' I had initially asked for I accepted your suggestion as solution... if you don't mind ;-)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900