Using Delegates While Threading

Bernie

Well-known member
Joined
Aug 13, 2007
Messages
98
Programming Experience
3-5
I'm just learning threading in VB and I'm having trouble using a delegate to sent information back to the main form. This is what I have;

The Main Form
VB.NET:
    Dim myThreadObject As ThreadObject

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myThreadObject = New ThreadObject
        AddHandler myThreadObject.ThreadFinished, AddressOf ThreadFinishedEventHandler
    End Sub

    Private Sub RunTheThread()
        Dim myThread As Threading.Thread

        ' run the thread ...
        myThread = New Threading.Thread(AddressOf myThreadObject.main)
        myThread.Start()
    End Sub

    Public Sub UpdateTextBox(ByVal message As String)
        tbOutput.Text = message
    End Sub

    Sub ThreadFinishedEventHandler()
        MessageBox.Show("Thread completed")
    End Sub

The Class Object to be the Thread
VB.NET:
Public Class ThreadObject

    Public Event ThreadFinished()
    Dim myUpdateTextBox As dlgUpdateTestBox

    Public Delegate Sub dlgUpdateTestBox(ByVal Message As String)

    Public Sub New()

        myUpdateTextBox = New dlgUpdateTestBox(AddressOf Form1.UpdateTextBox)

    End Sub

    Public Sub main()
        MessageBox.Show("Thread running")

        myUpdateTextBox("Thread is finished")
        RaiseEvent ThreadFinished()
    End Sub

End Class

When I run this test code, I get the messageboxes indicating the thread is running, the event is raised and caught, but the call back to the text box on the main form is not working. Can anyone point me in the right direction here?

Thanks,
Bernie
 
The problem is that at no point do you marshal a method call back to the UI thread. Your ThreadObject is raising its ThreadFinished event in a background thread. You need to do one of two things:

1. Marshal a method call to the UI thread in the ThreadObject object so you can raise the event on the UI thread.

2. Handle the event in the form on the background thread and then marshal a method call to the UI thread to access your control(s).

Here's some information on threading and delegates that explains the second option and forms the basis for the first. Here's an extension of that that implements the first option.
 
Thanks for the quick reply and great info!

So I now have this;
Main Form
VB.NET:
    Dim myThreadObject As ThreadObject
    Public Delegate Sub UpdateTextBoxInvoker(ByVal message As String)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        myThreadObject = New ThreadObject(Me)
        AddHandler myThreadObject.ThreadFinished, AddressOf ThreadFinishedEventHandler
    End Sub

    Private Sub RunTheThread()
        Dim myThread As Threading.Thread

        ' run the thread ...
        myThread = New Threading.Thread(AddressOf myThreadObject.ThreadBegin)
        myThread.Start()

    End Sub


    Public Sub UpdateTextBox(ByVal message As String)

        If Me.tbOutput.InvokeRequired Then
            Me.tbOutput.BeginInvoke(New UpdateTextBoxInvoker(AddressOf UpdateTextBox), message)
        Else
            tbOutput.Text = message
        End If
    End Sub

Thread Object Class
VB.NET:
Public Class ThreadObject

    Dim _parentForm As Form1

    Public Sub New(ByVal parent)

        _parentForm = parent

    End Sub

    Public Sub ThreadBegin(ByVal parentForm As Form1)

       _parentForm.UpdateTextBox("Thread is finished")

    End Sub

End Class

Do I have everything correctly covered?

thanks,
Bernie
 
Back
Top