Getting a return value is no more difficult. One thing I haven't mentioned is that the Invoke method is a function. If the method invoked by the delegate returns a value then that is propagated by the Invoke method. Let's use an example of getting the Text property of a TextBox. Following the steps laid out already we first create a method to do the job:
CSharp Code:
private string[] GetRichTextBoxLines()
{
return this.rtbSongs.Lines;
}
Next we declare a matching delegate:
CSharp Code:
private delegate string[] GetRichTextBoxLinesInvoker();
private string[] GetRichTextBoxLines()
{
return this.rtbSongs.Lines;
}
After that we test the InvokeRequired property:
CSharp Code:
private delegate string[] GetRichTextBoxLinesInvoker();
private string[] GetRichTextBoxLines()
{
if (this.rtbSongs.InvokeRequired)
{
}
else
{
return this.rtbSongs.Lines;
}
}
Finally we call the Invoke method and pass an instance of our delegate:
CSharp Code:
private delegate string[] GetRichTextBoxLinesInvoker();
private string[] GetRichTextBoxLines()
{
if (this.rtbSongs.InvokeRequired)
{
return (string[])this.rtbSongs.Invoke(new GetRichTextBoxLinesInvoker(GetRichTextBoxLines));
}
else
{
return this.rtbSongs.Lines;
}
}
Let's clean that up a little so we only have one Return statement, which is widely considered to be best practice:
CSharp Code:
private delegate string[] GetRichTextBoxLinesInvoker();
private string[] GetRichTextBoxLines()
{
string[] lines;
if (this.rtbSongs.InvokeRequired)
{
lines = (string[])this.rtbSongs.Invoke(new GetRichTextBoxLinesInvoker(GetRichTextBoxLines));
}
else
{
lines = this.rtbSongs.Lines;
}
return lines;
}
Notice that in this case we are actually returning the result of the Invoke method, which is the same value as was returned by the method that was invoked. This is how you get a value back onto your worker thread from the UI thread.
Notice also that the return value from the invoke method must be cast as the appropriate type. Invoke can be used to invoke any method at all, so it could return any value at all. That means that its actual return type is Object. You must therefore cast each returned object as its actual type.
Now to show that this method can be generalised to any control too, as well as combine the passing of parameters and returning a value, here's an extended example based on what we've already seen:
CSharp Code:
private delegate string[] GetTextBoxLinesInvoker(TextBoxBase ctl);
private string[] GetTextBoxLines(TextBoxBase ctl)
{
string[] lines;
if (ctl.InvokeRequired)
{
lines = (string[])ctl.Invoke(new GetTextBoxLinesInvoker(GetTextBoxLines),
ctl);
}
else
{
lines = ctl.Lines;
}
return lines;
}