Julius Malundras
Julius Malundras

Reputation: 7

How to pause loop while multithreading is alive

I have 3 threads that are called inside a loop.

For i As Integer = 0 To DG.Rows.Count - 1
    Dim thread1 = New System.Threading.Thread(AddressOf processData)
    Dim thread2 = New System.Threading.Thread(AddressOf processData2)
    Dim thread3 = New System.Threading.Thread(AddressOf processData3)
    If Not thread1.IsAlive Then
       x1 = i
       thread1.Start()
    ElseIf Not thread2.IsAlive Then
       x2 = i
       thread2.Start()
    ElseIf Not thread3.IsAlive Then
        x3 = i
        thread3.Start()
    End If
Next

How do I pause the loop while all threads are alive? What I want is, if one of the threads finishes then continue the loop and get the (i), then pause the loop again if there are no available threads. Because sometimes DG.Rows items are more than 3.

Upvotes: 0

Views: 283

Answers (3)

Enigmativity
Enigmativity

Reputation: 117029

It could be that you use TPL's Parallel methods and write your code like this:

Parallel.For( _
    0, _
    DG.Rows.Count, _
    New ParallelOptions() With {.MaxDegreeOfParallelism = 3}, _
    Sub(i) processData(i))

I don't understand why you have processData, processData2, and processData3 though.

Upvotes: 0

Joel Coehoorn
Joel Coehoorn

Reputation: 415630

Let the framework handle this for you: use the ThreadPool.

First, create an array to hold thread status for each item:

Dim doneEvents(DG.Rows.Count) As ManualResetEvent

Like the x1,x2,x3 variables, this needs to be accessible from both your main thread and the processData method.

Then modify your processData method to accept an Object argument at the beginning and set a ResetEvent at the end:

Public Sub processData(ByVal data As Object)
   Dim x As Integer = CInt(data)

    '...
    'Existing code here

    doneEvents(x).Set()
End Sub

Now you can just queue them all up like this:

For i As Integer = 0 To DG.Rows.Count - 1
    ThreadPool.QueueUserWorkItem(processData, i)
Next
WaitHandle.WaitAll(doneEvents)
Console.WriteLine("All data is processed.")

Though I suspect you should also pass the data from your grid for each row to the processData method.

You can also use the newer Async/Await keywords, but I'll have a hard time writing a sample for this without knowing something of the contents of processData.

Upvotes: 3

Mark Lakata
Mark Lakata

Reputation: 20818

I think you want to do something like this. Don't pause, just launch a thread per loop iteration.

For i As Integer = 0 To DG.Rows.Count - 1
    Dim thread1 = New System.Threading.Thread(AddressOf processData)
    thread1.Start(i)
Next

But in any case, I don't think you want to call new System.Threading.Thread in each loop. Those should be moved outside the For loop.

Upvotes: 0

Related Questions