To invoke a method via a delegate, the delegate must have the same signature as the method. The example in the first post invokes a method that has no parameters and no return value. In that case you can use the existing MethodInvoker delegate. If you need to specify one or more parameters or get a return value though, you will have to declare your own delegate type.
Let's say that you want to set the Text property of a TextBox from a worker thread. From the first post we know the first step is to declare a method that does what we want:
vb.net Code:
Private Sub SetTextBoxText(ByVal text As String)
Me.TextBox1.Text = text
End Sub
Now, that method has a parameter so we cannot use the MethodInvoker delegate. We must declare our own delegate type with the same signature. The signature is basically the parameter list and the return type. To create your delegate declaration you should copy the method declaration:
vb.net Code:
Private Sub SetTextBoxText(ByVal text As String)
then add the 'Delegate' key word:
vb.net Code:
Private Delegate Sub SetTextBoxText(ByVal text As String)
and finally change the name:
vb.net Code:
Private Delegate Sub SetTextBoxTextInvoker(ByVal text As String)
Now that we have declared our new delegate type we can create instances of it just as we did with the MethodInvoker.
The next step from above was to add a test for the InvokeRequired property of our control:
vb.net Code:
Private Sub SetTextBoxText(ByVal text As String)
If Me.TextBox1.InvokeRequired Then
Else
Me.TextBox1.Text = text
End If
End Sub
Finally we call the control's Invoke method and pass our delegate:
vb.net Code:
Private Sub SetTextBoxText(ByVal text As String)
If Me.TextBox1.InvokeRequired Then
Me.TextBox1.Invoke(New SetTextBoxTextInvoker(AddressOf SetTextBoxText), _
text)
Else
Me.TextBox1.Text = text
End If
End Sub
Notice that, while last time the only parameter passed to the Invoke method was the delegate, this time we pass the 'text' value as well. Any parameters passed to Invoke after the delegate will then be passed again to the method that gets invoked by the delegate. Our delegate will be invoking the SetTextBoxText method, which requires a 'text' parameter. That code gets the 'text' value passed in to the first call and propagates it to the second call via the Invoke method and the delegate.
The above example passes a single parameter but the very same mechanism can be used to pass multiple parameters. Here's a similar example that can be used to set the Text property of any control:
vb.net Code:
Private Delegate Sub SetControlTextInvoker(ByVal ctl As Control, ByVal text As String)
Private Sub SetControlText(ByVal ctl As Control, ByVal text As String)
If ctl.InvokeRequired Then
ctl.Invoke(New SetControlTextInvoker(AddressOf SetControlText), _
ctl, _
text)
Else
ctl.Text = text
End If
End Sub
Pass in the control and the text and the method handles the rest. It tests the InvokeRequired property and calls the Invoke method of the appropriate control, then sets the Text property of that same control.
EDIT: A note for those using .NET 1.x. The Control.Invoke method signature changed in .NET 2.0 to accept any number of individual parameters. Previous versions required any parameters to be passed within an array. That means that while this is fine in .NET 2.0 and above:
vb.net Code:
ctl.Invoke(New SetControlTextInvoker(AddressOf SetControlText), _
ctl, _
text)
you would have to do this in .NET 1.x:
vb.net Code:
ctl.Invoke(New SetControlTextInvoker(AddressOf SetControlText), _
New Object() {ctl, _
text})