One commonality shared by most Windows Forms applications is the need for a responsive UI; this means implementing some sort of threading scheme so that processes can run on background threads so as to not interrupt the user's workflow while using the various controls placed on the UI itself. The caveat to this is that the CLR does not allow cross threading updates to classes that inherit from System.Windows.Forms.Control, i.e. the control cannot be updated from a thread that wasn't responsible for the creation of the control. There is a pattern exposed by the BCL that enables this kind of programming: You need to declare a delegate which will act as the pointer to the method to update the control, then in your main code block check for Control.InvokeRequired, and finally call Control.BeginInvoke passing in your delegate as the argument.
The end result ends up looking something like this:
public class Foo : Form
{
public static void Main()
{
Application.Run(new Foo());
}
public Foo()
{
InitializeComponent();
}
private delegate void ConsoleWriterDelegate();
private void DoSomeWork()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new ConsoleWriterDelegate(WriteToConsole));
}
}
private void WriteToConsole()
{
Console.WriteLine("Writing to console via explicit delegate ");
}
}
In this case, we've really just written a delegate simply for the sake of creating one. You'll also notice that we aren't passing any parameters to the WriteToConsole method. This is a simple programming idiom made more complicated than it actually should be. Fortunately there's a delegate exposed by the BCL just for cases like this, System.Windows.Forms.MethodInvoker. Couple this delegate with anonymous methods in C# 2.0 and we can make the DoSomeWork method from above much simpler:
private void DoSomeWork()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
Console.WriteLine("Writing to console via anonymous method. ");
}));
}
}
For simple cross thread calls that need to interact with controls, this pattern is much simpler to implement and we get the added performance gains of using MethodInvoker. This code idiom will also work with Control.Invoke.
Posted
Feb 14 2007, 05:35 PM
by
Jayson Knight