Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VB.NET Multithreading. Calling invoke on a UI Control from a class in a separate class file

I've been trying to understand this for a few days now and wonder if it's something simple I'm missing or doing completely wrong.

Example: Two files - TestClass.vb, myForm.vb


TestClass.vb looks as follows:

Imports System.Threading

Public Class TestClass
    Private myClassThread As New Thread(AddressOf StartMyClassThread)

    Public Sub Start()
        myClassThread.Start()
    End Sub

    Private Sub StartMyClassThread()
        myForm.Msg("Testing Message")
    End Sub
End Class

myForm.vb is a basic form with a listbox control and a button control named respectively Output and StartButton. The code behind the form is as follows:

Public Class myForm
    Private classEntity As New TestClass

    Private Sub StartButton_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                              Handles StartButton.Click
        Msg("Start Button Pressed")
        classEntity.Start()
    End Sub

    Delegate Sub MsgCallBack(ByVal mesg As String)

    Public Sub Msg(ByVal mesg As String)
        If Output.InvokeRequired Then
            MsgBox("Invoked")
            Dim d As New MsgCallBack(AddressOf Msg)
            Invoke(d, New Object() {mesg})
        Else
            MsgBox("Not Invoked")
            mesg.Trim()
            Output.Items.Add(mesg)
        End If
    End Sub
End Class

The result:

Application runs, no errors or exceptions. Displayed is the listbox and the Start button. I press the start button and a msgbox says "Not Invoked" as expected and upon clicking OK to that msgbox "Start Button Pressed" is added to the Output listbox control. Immediately following that the msgbox pops up again and says "Not Invoked". I was expecting "Invoked" as a separate thread is trying to use the Output listbox control. Of course this results in the Output.Items.Add being attempted which results in no visible result as the thread is not allowed to directly update the UI control.

I must've read a small books worth of different pages trying to thoroughly understand pit falls and methods but I feel I may have fallen into a trap alot of people may do. With my current understanding and knowledge I'm unable to get out of that trap and would appreciate any input or advice.

Kind regards,

Lex

like image 685
Lecronox Avatar asked May 13 '11 10:05

Lecronox


1 Answers

The problem here is that you are calling the function Msg not on an instance of myForm, but as a shared function of the class myForm.

Change your code in TestClass to add

Public FormInstance as myForm

and then replace

myForm.Msg("Testing Message")

with

FormInstance.Msg("Testing Message")

Then in StartButton_Click add the line

classEntity.FormInstance = Me

and you will get the expected result.

like image 129
Soumya Avatar answered Oct 24 '22 02:10

Soumya