user7088516
user7088516

Reputation:

Multithreading doesn't work

I'm making a simple multithreading program to explain the working of threading. I want two counters counting on the same time but it doesn't work.

It only works if I use: CheckForIllegalCrossThreadCalls = False. But, I want to program in a proper way.

Code:

Dim Thread1 As System.Threading.Thread
Dim Thread2 As System.Threading.Thread

Private Delegate Sub SetTeller1()

Private Sub teller1()
    If teller1Label.InvokeRequired Then
        Invoke(New SetTeller1(AddressOf teller1))
    Else
        For i As Integer = 0 To 1000
            teller1Label.Text = i
            Refresh()
        Next
    End If
End Sub

Delegate Sub SetTeller2()

Private Sub teller2()
    If teller2Label.InvokeRequired Then
        Invoke(New SetTeller2(AddressOf teller2))
    Else
        For i As Integer = 0 To 1000
            teller2Label.Text = i
            Refresh()
        Next
    End If
End Sub

Private Sub teller1Button_Click(sender As Object, e As EventArgs) Handles teller1Button.Click
    Thread1 = New Threading.Thread(AddressOf teller1)
    Thread1.Start()
End Sub

Private Sub teller2Button_Click(sender As Object, e As EventArgs) Handles teller2Button.Click
    Thread2 = New Threading.Thread(AddressOf teller2)
    Thread2.Start()
End Sub

Upvotes: 1

Views: 122

Answers (1)

Visual Vincent
Visual Vincent

Reputation: 18310

The multithreading works perfectly, but you are not utilizing it. The only thing you're currently doing in the background thread is calling Invoke, which means that your thread will exit within a few milliseconds and then be discarded.

Once you call Invoke the execution of the teller1 or teller2 method is moved to the UI thread, meaning it will block the UI until its execution is finished. You should only invoke when you are to update the UI, and perform all iterations in the background thread.

Here's an example of how you can do it more properly:

Delegate Sub SetTeller1(ByVal Text As String)

Private Sub teller1()
    For i As Integer = 0 To 1000
        SetTeller1Text(i)
    Next
End Sub

Private Sub SetTeller1Text(ByVal Text As String)
    If Me.InvokeRequired Then
        Me.Invoke(New SetTeller1(AddressOf SetTeller1Text), Text)
    Else
        teller1Label.Text = Text
        Me.Refresh()
    End If
End Sub

For improved readability I changed for example Invoke(...) to Me.Invoke(...).

Also I'm not sure why you're calling Refresh() as it isn't necessary and will just cause extra redrawing of the entire container (guessing this is a form).

Upvotes: 2

Related Questions