Cross-thread operation not valid: Control ‘ControlName’ accessed from a thread other than the thread it was created on


A multithreaded process with two threads execu...

Image via Wikipedia

This is a common error when you are developing a multithreading application you often recieve an InvalidOperationException
indicating that a thread is trying to access an object that was created on another thread. A typical code block that generates this
error is shown below :

Dim th As New Threading.Thread(AddressOf test)
 

Private Sub test()
    TextBox1.Text = "using textbox from another thread"
End Sub


Private Sub Form1_Load(ByVal sender As System.Object, _ 
 ByVal e As System.EventArgs) Handles MyBase.Load
     th.Start()
End Sub

In the code above, TextBox1 is a normal textbox placed in the form. As we predicted, the error is thrown because TextBox1 belongs to main thread
, which is the single thread that runs the form and th is another thread accessing the textbox from the test function. To resolve
this problem, each control must be exclusively accessed from it belonging thread. What we are talking about here is to apply
context switching whenever we need to access controls on different threads. This is easy to do in .net framework. In face, we can
also add a small functionality to check whether a cross threading operation is required before we actually go on and swtich the context
because context switching has its performance penalties.

Using the Invoke method of the form, we can pass in a MethodInvoker object, which is a delegate specifying the address of the
function that we would like to invoke in case if an invokation is required by the form’s thread. To do the actual testing if an invokation
is needed, we use the form’s InvokeRequired property. Below is the working version of the code:

Dim th As New Threading.Thread(AddressOf test)
 

Private Sub test()
      If Me.InvokeRequired Then
             Me.Invoke(New MethodInvoker(AddressOf test))
       Else
                TextBox1.Text = "using textbox from another thread"
        End If
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, _ 
 ByVal e As System.EventArgs) Handles MyBase.Load
     th.Start()
End Sub

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: