Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my thread not starting immediately?

see below program. I start a new thread x with function abc, then I do some longer task. Why does x only start after end sub? Shouldn't it start right-away, before sleep ?

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim x As New Threading.Thread(AddressOf abc)
        x.SetApartmentState(Threading.ApartmentState.MTA)
        x.Start()

        System.Threading.Thread.Sleep(5000)
    End Sub





Sub abc()
    For i As Integer = 0 To 10 Step 1
        Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )"
        'Me.StatusStrip1.Invoke(
        MsgBox(i.ToString)
        System.Threading.Thread.Sleep(1000)
    Next
End Sub



Edit:
The solution is this:

(A) Put both the connection attempts and the timeout countdown into separate threads.
(B) Update the UI like this:

    If Me.InvokeRequired Then
        Me.Invoke(pUpdateStatusMessage, "Successfully connected.")
    Else
        UpdateStatusMessage("Successfully connected.")
    End If

With this globally declared, so no argument passing is necessary:

Delegate Sub t_pUpdateStatusText(ByVal strMessage As String)
Public pUpdateStatusMessage As t_pUpdateStatusText = New t_pUpdateStatusText(AddressOf UpdateStatusMessage)

Public Sub UpdateStatusMessage(ByVal strMessage As String)
    Me.lblStatus.Text = strMessage
    Me.StatusStrip1.Update()
End Sub
like image 675
Stefan Steiger Avatar asked Dec 22 '22 22:12

Stefan Steiger


1 Answers

The abc function will indeed start before the Button1_Click method ends. What's causing the confusion is 2 things

The first is that you are directly updating the UI from a background thread with the following line

Me.lblStatus.Text = "Testing DB connection ( timeout in: " + i.ToString() + "s )" 

This code is incorrect and can cause issues later on. You must use the Invoke call in order to actually change the UI. As you do in the second line which brings us to the next problem.

The Invoke call is synchronous. It runs by essentially pushing a message onto the windows message queue and waiting for it to be processed before returning. The Thread.Sleep call you added in the main thread prevents the message queue from actually running. This effectively stalls the background thread until the Sleep call completes giving the appearance that the background thread is not running.

like image 194
JaredPar Avatar answered Dec 24 '22 11:12

JaredPar