Make InvokeRequired/Invoke easy
Posted on : 23-01-2009 | By : manitra | In : C#, Developpement, WinForm
5
The problem
If you’re working on WinForms, you must know that you cannot call controls methods within a thread that is not the one that created those controls. To solve this problem, Microsoft recommend us to use the following code :
-
namespace TestWinForm
-
{
-
public partial class MainForm : BaseForm
-
{
-
public MainForm()
-
{
-
InitializeComponent();
-
}
-
// a delegate that has been created specially for this method
-
private delegate void DisplayDelegate(string text);
-
-
// a method that may be called from a worker thread
-
public virtual void Display(string text)
-
{
-
if (InvokeRequired)
-
{
-
Invoke(new DisplayDelegate(Display));
-
}
-
else
-
{
-
//the actual job is here
-
textBox1.AppendText(text);
-
}
-
}
-
}
-
}
This code is ugly because :
- you need to create a delegate for each single public method you can call from outside
- you need to put an “if/else” block in each method wich increase the complexity of your code
The trick
Here is a trick that could significantly reduce the amount of code needed to do the same job within a large project.
Within you base class
You probably have a common base class for all your UI components. Add this method :
-
namespace TestWinForm
-
{
-
public class BaseForm : Form
-
{
-
// This allows a sub class to easily run a method within
-
// an UI thread without the need of creating multiple
-
// delegate signatures for each method signatures
-
protected virtual void ThreadSafe(MethodInvoker method)
-
{
-
if (InvokeRequired)
-
Invoke(method);
-
else
-
method();
-
}
-
}
-
}
Within your UI classes
Now the only thing you need to do is to encapsulate the methode content with the ThreadSafe() method :
-
namespace TestWinForm
-
{
-
public partial class MainForm : BaseForm
-
{
-
public MainForm()
-
{
-
InitializeComponent();
-
}
-
-
// public method that may be called from outside and within any
-
// worker thread …
-
public virtual void Display(string text)
-
{
-
ThreadSafe(delegate
-
{
-
//do any UI related code here
-
//note that because this is an anonym method,
-
//you can use the local parameter
-
textBox1.AppendText(text);
-
});
-
}
Happy coding !

