-1

I have a function that initializes and kicks off a maximum of four simultaneous threads. Roughly explained, each thread calls an external executable with some custom arguments.

While debugging it seems that the four instances of the executable are all kicked off simultaneously; immediately after the entire function has been completed and has returned "True". This causes my simulations to crash.

Here is a video of the debugging process: https://www.dropbox.com/s/7tgcs6df8sfve2t/Debugging_multithreading_VB.mp4?dl=0

I would however have expected each executable to be kicked off immediately after ThreadX.Start().

What am I doing wrong?

Public Function Run() As Boolean
    Try
        Dim EventNum As Integer
        Dim RowNum As Integer = 0

        'make a list of 4 simultaneous threads
        'Dim Threads As New List(Of Threading.Thread)

        Dim Thread1 As Threading.Thread
        Dim Thread2 As Threading.Thread
        Dim Thread3 As Threading.Thread
        Dim Thread4 As Threading.Thread

        For Each myRow As DataGridViewRow In grEvents.SelectedRows
            RowNum += 1
            EventNum = myRow.Cells(0).Value         'get the event number from the selected row
            Debug.Print("Current event " & EventNum)

            'Dim debugSim As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
            'debugSim.Run()

            If RowNum <= 4 Then
                Select Case RowNum
                    Case Is = 1
                        Dim Sim1 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread1 = New Threading.Thread(AddressOf Sim1.Run)
                        Thread1.Start()
                    Case Is = 2
                        Dim Sim2 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread2 = New Threading.Thread(AddressOf Sim2.Run)
                        Thread2.Start()
                    Case Is = 3
                        Dim Sim3 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread3 = New Threading.Thread(AddressOf Sim3.Run)
                        Thread3.Start()
                    Case Is = 4
                        Dim Sim4 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread4 = New Threading.Thread(AddressOf Sim4.Run)
                        Thread4.Start()
                End Select
            Else
                'all threads are occupied. wait for one to become available
                Dim SimulationStarted As Boolean = False
                While Not SimulationStarted
                    If Thread1.ThreadState = Threading.ThreadState.Stopped Then
                        UpdateEventsGrid()                      'after each completed simulation we can update the events grid with the fact that we have new results available
                        Dim Sim1 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread1 = New Threading.Thread(AddressOf Sim1.Run)
                        Thread1.Start()
                        SimulationStarted = True
                    ElseIf Thread2.ThreadState = Threading.ThreadState.Stopped Then
                        UpdateEventsGrid()                      'after each completed simulation we can update the events grid with the fact that we have new results available
                        Dim Sim2 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread2 = New Threading.Thread(AddressOf Sim2.Run)
                        Thread2.Start()
                        SimulationStarted = True
                    ElseIf Thread3.ThreadState = Threading.ThreadState.Stopped Then
                        UpdateEventsGrid()                      'after each completed simulation we can update the events grid with the fact that we have new results available
                        Dim Sim3 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread3 = New Threading.Thread(AddressOf Sim3.Run)
                        Thread3.Start()
                        SimulationStarted = True
                    ElseIf Thread4.ThreadState = Threading.ThreadState.Stopped Then
                        Dim Sim4 As clsSobekSimulation = Simulations.Item(EventNum)      'select the corresponding simulation
                        Thread4 = New Threading.Thread(AddressOf Sim4.Run)
                        Thread4.Start()
                        SimulationStarted = True
                    End If
                    Threading.Thread.Sleep(2000)
                End While
            End If
            UpdateEventsGrid()                      'after each completed simulation we can update the events grid with the fact that we have new results available
        Next
        Return True
    Catch ex As Exception
        Me.Setup.Log.AddError(ex.Message)
        Me.Setup.Log.AddError("Error running simulations.")
        Return False
    End Try
End Function
  • Without having tested myself, I'm guessing that it's because you're using breakpoints. I think that, by default, all threads break when your code hits a breakpoint. Your threads are probably not getting a chance to kick off because of all the breaking. I'd suggest using some tracing instead, so you can just let the code run and each thread will log where it is up to and when. You can then see the exact time that each thread started and compare that to when you method ends. – jmcilhinney Mar 29 '20 at 03:05

1 Answers1

0

I believe https://stackoverflow.com/users/584183/jmcilhinney is right in that the issue described did not cause the problem at all and that the threads were not kicked off due to the many breakpoints.

In the meantime I have learned that the thread I was executing contained an incomplete configuration of System.Diagnostics.Process. I applied the advice from https://stackoverflow.com/a/33633148/7154075 to improve the way my command line executable was started and this seems to have solved the entire problem.