I needed this to show a modal dialog from a separate thread, but in a way that I could actually get a return value from it, too. Vokinneberg's answer put me on the right track, but I still needed something more.
The final solution I came up with was to add this, as function-version of MethodInvoker
:
public delegate Object FunctionInvoker();
Now, if I have a function like this, which shows a modal dialog and returns data from it...
Dictionary<int, string> ShowDataDialog(byte[] data, Form parent)
{
using (DataDialog dd = new DataDialog(data))
{
if (dd.ShowDialog(parent) != DialogResult.OK)
return null;
return dd.MappedData;
}
}
...it can be called like this from the different thread:
Dictionary<int, string> mappedData =
(Dictionary<int, string>)parent.Invoke(
(FunctionInvoker)(() => ShowNewFromImageDialog(data, parent)));
Now, everything works: the function is invoked on the main form, the dialog is shown as modal dialog of the main form, and the value from the dialog is returned to the other thread, which can continue its processing.
There's still some ugly casts in there, because Control.Invoke
happens to return an Object, but still, it can be used for any function, as long as there are no advanced things like output-parameters involved.
It's probably possible to make this cleaner, as extension method on Form
or something, that does the casts internally, if I work with generics. But for now, this'll do.