Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
 
TitleLet a Thread call a form's methods in VB.NET
DescriptionThis example shows how to let a Thread call a form's methods in VB.NET.
Keywordsthread, multi-threading, SyncLock, asynchronous, threading, Invoke, InvokeRequired
CategoriesVB.NET
 
When the user clicks the Start Thread button, the program makes a new Counter object and a Thread, initializing it to execute the Counter's Run method.

The program sets the Thread's IsBackground property to True so it will automatically stop when the program's main thread stops. If you don't do this, the Thread will keep running until its Run method exits (which it never does so it would run until it reached an overflow problem).

The program then calls the Thread's Start method.

The form's DisplayValue method adds a string to the txtResults TextBox.

 
Imports System.Threading
...
' This value is incremented by the thread.
Public Value As Integer = 0

Private Sub btnStartThread_Click(ByVal sender As _
    System.Object, ByVal e As System.EventArgs) Handles _
    btnStartThread.Click
    ' Make a new counter object.
    Static thread_num As Integer = 0
    Dim new_counter As New Counter(Me, thread_num)
    thread_num += 1

    ' Make a thread to run the object's Run method.
    Dim counter_thread As New Thread(AddressOf _
        new_counter.Run)

    ' Make this a background thread so it automatically
    ' aborts when the main program stops.
    counter_thread.IsBackground = True

    ' Start the thread.
    counter_thread.Start()
End Sub

' Add the text to the results.
' The form provides this service because the
' thread cannot access the form's controls directly.
Public Sub DisplayValue(ByVal txt As String)
    txtResults.Text &= vbCrLf & txt
    txtResults.Select(txtResults.Text.Length - 1, 0)
    txtResults.ScrollToCaret()
End Sub
 
A Counter object increments the form's Value variable and displays the result in the form's txtResults TextBox.

The Run method enters an infinite loop. It sleeps for 1 second and then uses a SyncLock statement to get a lock on the form. This doesn't do anything to the form, it just means no other thread can lock the form object until we release the lock. To see why this is important, suppose the form's Value variable holds the value 1. Then suppose two threads are running and both enter this section of code at approximately the same time and follow this sequence of events:

  • Object 1 increments the form's Value property to 2.
  • Object 2 increments the form's Value property to 3.
  • Object 1 displays the form's Value property 3.
  • Object 2 displays the form's Value property 3.

Instead of displaying the value 2 and then 3, both of the threads display the value 3.

After it locks the form object, the Counter increments Value. It then uses the form's InvokeRequired method to see if the code is running on a Thread other than the one that created the form. If it is (and we know it is in this example), then it cannot access the form's methods directly.

Instead, the program calls the form's Invoke method. This method's first parameter is a delegate indicating the form routine to execute. Its second parameter is an array of parameters to pass to the form routine. In this case, the parameter array contains the text that the DisplayValue method should display.

The object then uses the End SyncLock statement to release its lock. If another thread reaches its SyncLock statement while this object holds a lock on the form, the second object waits until the lock is released.

 
' This class's Run method displays a count in the Output
' window.
Public Class Counter
    ' The form that owns the Value variable.
    Private m_MyForm As Form1

    ' Define a delegate type for the form's DisplayValue
    ' method.
    Private Delegate Sub DisplayValueDelegateType(ByVal txt _
        As String)

    ' Declare a delegate variable to point
    ' to the form's DisplayValue method.
    Private m_DisplayValueDelegate As _
        DisplayValueDelegateType

    ' This counter's number.
    Private m_Number As Integer

    Public Sub New(ByVal my_form As Form1, ByVal my_number _
        As Integer)
        m_MyForm = my_form
        m_Number = my_number

        ' Initialize the delegate variable to point
        ' to the form's DisplayValue method.
        m_DisplayValueDelegate = AddressOf _
            m_MyForm.DisplayValue
    End Sub

    ' Count off seconds in the Output window.
    Public Sub Run()
        Try
            Do
                ' Wait 1 second.
                Thread.Sleep(1000)

                ' Lock the form object. This doesn't do
                ' anything
                ' to the form, it just means no other
                ' thread can
                ' lock the form object until we release the
                ' lock.
                ' That means a thread can update
                ' m_MyForm.Value
                ' and then display its value without
                ' interference.
                SyncLock m_MyForm
                    ' Increment the form's Value.
                    m_MyForm.Value += 1

                    ' Display the value on the form.
                    ' The call to InvokeRequired returns
                    ' True
                    ' if this code is not running on the
                    ' same
                    ' thread as the object m_MyForm. In this
                    ' example, we know that is true so the
                    ' call
                    ' isn't necessary, but in other cases it
                    ' might not be so clear.
                    If m_MyForm.InvokeRequired() Then
                        ' Make an array containing the
                        ' parameters
                        ' to pass to the method.
                        Dim args() As String = {m_Number & _
                            ": " & m_MyForm.Value}

                        ' Invoke the delegate.
                        m_MyForm.Invoke(m_DisplayValueDelegate, _
                            args)
                    End If
                End SyncLock
            Loop
        Catch ex As Exception
            ' An unexpected error.
            Debug.WriteLine("Unexpected error in thread " & _
                _
                m_Number & vbCrLf & ex.Message)
        End Try
    End Sub
End Class
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated