WooHoo - back into actually doing some development after a stint doing some Flash Actionscript work and conducting a 4 week testing phase (possibility one of my favourite tasks).
Anyhoo, let's say you're trying to update a UI element from the non-UI worker thread using similar code to the following...
' Single form, one button called 'butExecute' and one label called 'lblTime'
Private
Sub butExecute_Click(
ByVal sender
As System.Object,
ByVal e
As System.EventArgs)
Handles butExecute.Click
Dim t As New Threading.Thread(AddressOf UpdateTime)
t.Start()
End SubPrivate
Sub UpdateTime()
' Updates the label with the appropriate Now time
Me.lblTime.Text = Now.ToString
End Sub . . .
When you clicked the button you would get a message along the following lines of...
"Cross-thread operation not valid: Control 'lblTime' accessed from a thread other than the thread it was created on."
...which basically means you cannot call any UI related methods / properties on any controls unless the call is made from the thread that created the control in the first place. So, the way to get around this would be to create a delegate that would invoke the method 'UpdateTime' on the UI thread, e.g. (my quick implementation)...
Private Delegate Sub UpdateTimeDelegate()
Private
Sub butExecute_Click(
ByVal sender
As System.Object,
ByVal e
As System.EventArgs)
Handles butExecute.Click
Dim t As New Threading.Thread(AddressOf SafeUpdateTime)
t.Start()
End SubPrivate
Sub SafeUpdateTime()
' Are we running on the main UI thread
If Me.InvokeRequired
Then' If not, create a new delegate and invoke the method
Me.Invoke(New UpdateTimeDelegate(AddressOf SafeUpdateTime))
Else' We're running on the main UI thread so...
' Updates the label with the appropriate Now time
Me.lblTime.Text = Now.ToString
End If
End Sub
. . .
Here we check whether we are running on the UI thread (using Me.InvokeRequired) and if are not we invoke the method on the UI thread.
However, there is a simplier way to do this without declaring an actual delegate - by creating an MethodInvoker object...
Private
Sub butExecute_Click(
ByVal sender
As System.Object,
ByVal e
As System.EventArgs)
Handles butExecute.Click
Dim t As New Threading.Thread(AddressOf SafeUpdateTime)
t.Start()
End SubPrivate
Sub SafeUpdateTime()
' Are we running on the main UI thread
If Me.InvokeRequired
Then' If not, create a new delegate and invoke the method
Me.Invoke(New MethodInvoker(AddressOf SafeUpdateTime))
Else' We're running on the main UI thread so...
' Updates the label with the appropriate Now time
Me.lblTime.Text = Now.ToString
End If
End Sub
. . .
Basically, the MethodInvoker class is intended to provide an accessible delegate object (without parameters) when you don't want to create the delegate yourself. Useful? Well, as daft as it sounds - yeah it is, and as a OO developer I always feel twitchy when copying/pasting/replacing parameterless delegate definitions.
HTH - M