vb.netmultithreadingdelegatesinvoke

Attempting - Multithreading - in VB.net Windows Forms


For a while now I have been using this code:

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim t2 As New Threading.Thread(AddressOf SetLabelText2)
    t2.IsBackground = True
    t2.Start()
End Sub

Delegate Sub UpdateDelegate()

Private Sub SetLabelText2()
    If InvokeRequired Then
        Invoke(New UpdateDelegate(AddressOf SetLabelText2))
    Else
        For i = 1 To 110
            Label2.Text = Text
            Threading.Thread.Sleep(200)
        Next
    End If
End Sub

This code runs fine, except its not Multithreading my Application and puts it into a Unresponsive State.

My Question is simple,

  1. How can I fix this ( The application I will be using will have SEVERAL Function calls within
    If InvokeRequired Then

        Invoke(New UpdateDelegate(AddressOf SetLabelText2))

    Else

       FunctionCall1()

       FunctionCall2()

       FunctionCall3()

    End If

they all work and take ahold of my UI Thread.

I have been searching for quite some time now, any help is appreciated.

-Edit- Also having issues while in a thread to read information from a form ... thanks for the help so far

EDIT ---

Ok, I have change my code around to look like

Delegate Sub setForm1PrgBarPerformStepdelegate(s As Integer) 
    Private Sub setForm1PrgBarPerformStep(ByVal s As Integer)
        If Form1.ProgressBar1.InvokeRequired Then
            Dim d As New setForm1lblAlltextdelegate(AddressOf setForm1PrgBarPerformStep)
            Form1.Invoke(d, New Object() {s})
        Else
            If s = 1 Then
            Form1.ProgressBar1.PerformStep()
        Else

        End If
    End If
End Sub

This piece of code is being called with setForm1PrgBarPerformStep(1) ' or 0

Which is called by my thread, (It works (the threading part - which is awesome btw), with the minor flaw of NOT doing the Perform Step - or any other UI changes I Code in the Private Sub setForm1PrgBarPerformStep()

Is there a good reason for this?


Solution

  • When your thread first hits SetLabelText2, InvokeRequired will be true so

    Invoke(New UpdateDelegate(AddressOf SetLabelText2))
    

    will be called.

    Now, what actually happens inside the Invoke call is that your thread is going to pass the delegate to the UI thread as a task. So the second, recursive call to SetLabelText2 will be done by the UI thread and your thread just sits and waits for the UI thread to return from SetLabelText2. So your UI blocks because the UI thread will be in a loop, setting the label text and sleeping, and doesn't get a chance to process messages/events.

    As a solution, instead of Sleep(200) you can call Application.DoEvents() inside your loop, but this may have side effects and is not recommended.

    A better solution is to restrict Invoke to the strictly necessary UI calls, in your example:

    Private Sub SetLabelText2()
        For i = 1 To 110
            'Label2.Text = Text
            Invoke(MyDelegateThatDoesNothingButSettingTheLabelText)
            Threading.Thread.Sleep(200)
        Next
    End Sub
    

    Now the Sleeping will be done by your thread and your UI remains responsive.