Results 1 to 13 of 13

Thread: Waiting for threaded work method to complete inside a threaded loop

  1. #1

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Waiting for threaded work method to complete inside a threaded loop

    I am using a threaded loop to spawn a work method, and then wait for the work method to complete before cycling another loop iteration. However, when I specify 4 steps in the loop, I am only getting two steps performed. Is there anything fundamentally wrong in this code? Any better way to do this.

    Code:
    Public AllThreadsDone As New System.Threading.AutoResetEvent(False)
    AllThreadsDone.Set
    
    
    Dim t = New Thread(AddressOf ThreadedLoop)
    t.IsBackground = True
    t.SetApartmentState(ApartmentState.STA)
    threadList.Add(t)
    
    Sub ThreadedLoop()
    
      For j = 0 to 3
        Dim t = New Thread(AddressOf DoWork)
        t.IsBackground = True
        t.SetApartmentState(ApartmentState.STA)
        threadList.Add(t)
    
        Dim t = New Thread(AddressOf waitforthreadcompletion)
        t.IsBackground = True
        t.SetApartmentState(ApartmentState.STA)
        t.Start()
    
        AllThreadsDone.WaitOne()
    
      Next j
    
    End Sub
    
    Sub DoWork()
    
      Thread.Sleep(10000
      WorkThreadDone.Set()
    
    End Sub
    
    Private Sub waitforthreadcompletion()
    
      Try
    retry:
      For Each t In threadList
        If t.IsAlive = True Then GoTo retry
      Next
      AllThreadsDone.Set()
      Exit Sub
      Catch
         GoTo retry
      End Try
    
    End Sub
    Last edited by pel11; Mar 28th, 2022 at 01:19 PM.

  2. #2
    PowerPoster Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Yaddlethorpe, North Lincolnshire, England.
    Posts
    2,331

    Re: Waiting for threaded work method to complete inside a threaded loop

    Hi,

    I think I'd've used four BackgroundWorkers, using 'BackgroundWorker1_DoWork' to run the first method.
    Then use BackgroundWorker1_RunWorkerCompleted to start 'BackgroundWorker2_DoWork' and 'BackgroundWorker2_RunWorkerCompleted' to start BGW3... etc.


    Poppa
    Along with the sunshine there has to be a little rain sometime.

  3. #3
    Banned
    Join Date
    Nov 2011
    Posts
    7,803

    Re: Waiting for threaded work method to complete inside a threaded loop

    You can use the Task class to perform the multi-threading. It has a lot of nice features including methods for waiting on Tasks:-
    Code:
    Imports System.Threading
    
    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim tasks As New List(Of Task)
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(200, $"Task 1")
                               End Sub))
    
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(2000, $"Task 2")
                               End Sub))
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(100, $"Task 3")
                               End Sub))
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(2500, $"Task 4")
                               End Sub))
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(2900, $"Task 5")
                               End Sub))
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(5000, $"Task 6")
                               End Sub))
    
            tasks.Add(Task.Run(Sub()
                                   DoWork(7500, $"Task 7")
                               End Sub))
    
    
            'Wait for all tasks to be done
            Task.WaitAll(tasks.ToArray)
    
            Debug.WriteLine("All tasks have been completed.")
    
        End Sub
    
    
        Private Sub DoWork(ByVal delay As Integer, ByVal taskName As String)
    
            Thread.Sleep(delay)
            Debug.WriteLine($"{taskName} has completed.")
    
        End Sub
    
    
    End Class
    You could use something similar for your looping algorithm.

  4. #4
    Banned
    Join Date
    Nov 2011
    Posts
    7,803

    Re: Waiting for threaded work method to complete inside a threaded loop

    Quote Originally Posted by Poppa Mintin View Post
    Hi,

    I think I'd've used four BackgroundWorkers, using 'BackgroundWorker1_DoWork' to run the first method.
    Then use BackgroundWorker1_RunWorkerCompleted to start 'BackgroundWorker2_DoWork' and 'BackgroundWorker2_RunWorkerCompleted' to start BGW3... etc.


    Poppa
    This is just my opinion but I really believe people should distance themselves from dinosaurs like BackgroundWorkers to do threading and asynchronous programming. I believe it's better to do it the modern way, through Async/Await and the Task class.

  5. #5

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    FYI, the threads need to be single apartment, so can Tasks handle this or will they throw a UI exception?

  6. #6

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    Need to find out if Tasks won't throw a UI error (when delegates are used), since single apartment threads will not. I can't use for example ThreadPool.QueueUserWorkItem(Sub(state) WorkMethod, t.token) since it results in a lot of UI exceptions.

  7. #7

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    Tasks are not single apartment, since I just tried one instead of a thread, and I received the ActiveX exception related to the UI that "the thread is not single apartment"

  8. #8
    Banned
    Join Date
    Nov 2011
    Posts
    7,803

    Re: Waiting for threaded work method to complete inside a threaded loop

    Why does the ApartmentState matter? Are you exposing it COM for use in VBA/VB6 or another COM client?

  9. #9

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    Yes, I am using Microsoft Excel 16.0 Object Library, and the Interop Excel library, which is Active X and passes arguments as COM. Below is a link to a Sept 2021 article at MS on embedding Excel in C#

    https://docs.microsoft.com/en-us/dot...nterop-objects
    Last edited by pel11; Mar 29th, 2022 at 10:56 AM.

  10. #10
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    37,551

    Re: Waiting for threaded work method to complete inside a threaded loop

    Quote Originally Posted by Niya View Post
    This is just my opinion but I really believe people should distance themselves from dinosaurs like BackgroundWorkers to do threading and asynchronous programming. I believe it's better to do it the modern way, through Async/Await and the Task class.
    I don't agree with that opinion. The point of the BGW is that it has a mechanism built into it to raise an event on the UI thread. When you don't need to do that, then it does make more sense to use Tasks, but if you need to be raising events on the UI thread, doing that with Tasks is a pain.

    One isn't superior to the other in all cases. Each has it's place.
    My usual boring signature: Nothing

  11. #11

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    Thanks, I think that by the time all the excess baggage for a Winforms app is brought into the discussion, the "parameters change", but yes, for straightforward work, Tasks seem like the way to go. I didn't mean to short-change any of the users who answered, but I did present use of single apartment threads. I also have a lot of textboxes updated and a treeview with icons called via delegates from threads - so UI is used an awful lot.

  12. #12
    Banned
    Join Date
    Nov 2011
    Posts
    7,803

    Re: Waiting for threaded work method to complete inside a threaded loop

    Quote Originally Posted by Shaggy Hiker View Post
    I don't agree with that opinion. The point of the BGW is that it has a mechanism built into it to raise an event on the UI thread. When you don't need to do that, then it does make more sense to use Tasks, but if you need to be raising events on the UI thread, doing that with Tasks is a pain.

    One isn't superior to the other in all cases. Each has it's place.
    Eh. I suppose. I only ever used the BGW once. I just found it incredibly clumsy to use. Even with the need to raise events on the UI thread, I still find it cleaner to just use Tasks or Threads purely:-
    Code:
    Public Class Form1
    
        Private WithEvents _counter As New Counter
        Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Await _counter.DoCount(10)
    
            MessageBox.Show("Count finished.")
    
        End Sub
    
        Private Sub _counter_CountTick(sender As Object, e As CountTickEventArgs) Handles _counter.CountTick
    
            Me.Invoke(Sub()
                          Label1.Text = e.Count.ToString
                      End Sub)
        End Sub
    End Class
    
    Public Class Counter
    
        Public Event CountTick As EventHandler(Of CountTickEventArgs)
        Public Async Function DoCount(ByVal count As Integer) As Task
    
            Await Task.Run(Sub()
                               For i = 1 To count
                                   RaiseEvent CountTick(Me, New CountTickEventArgs(i))
                                   Threading.Thread.Sleep(1000)
                               Next
                           End Sub)
    
        End Function
    
    
    End Class
    
    Public Class CountTickEventArgs
        Inherits EventArgs
    
        Public Sub New(ByVal c As Integer)
            Me.Count = c
        End Sub
        Public ReadOnly Property Count As Integer
    
    
    End Class
    I donno...I just find this so much more straightforward and flexible.

  13. #13

    Thread Starter
    Member
    Join Date
    Mar 2022
    Posts
    39

    Re: Waiting for threaded work method to complete inside a threaded loop

    @Niya, thanks a lot. If the loop is not threaded, is there a trick for using something like WaitOne() to ensure all threads are completed? Using WaitOne() in a non-threaded evironment will stop all processing and threads will stop when the code stops on WaitOne(). However if Waiting is used in a threaded loop, the other threads will complete and finish. The problem I am facing is that it seems impossible to wait for thread completion in non-tgreaded code. That is if you simply start 5 threads in a Button1, and wait for threads to complete, somehow, the UI and the threads will lock up. You could launch a task after the thread initiation,vexe ute all the code in Button1, and then the task will notify when threads are completed. However, I need to stop at the bottom of the loop and wait, but the loop can't be threaded?

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width