free geoip Using Anonymous Methods For Control.Invoke/Control.BeginInvoke - Jayson's Blog - jaysonKnight.com
jaysonKnight.com
Welcome to my corner of the internet

Using Anonymous Methods For Control.Invoke/Control.BeginInvoke

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

4 Comments

DotNetKicks.com wrote Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on 02-14-2007 3:38 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Thomas Freudenberg wrote re: Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on 02-16-2007 4:06 AM

lol, Jayson, I stumbled over that myself a couple of days ago, but you beat me to blog about it Wink

Anyway, my solution is slightly different: instead of creating a new MethodInvoker object, I just cast the delegate. Don't know if the IL  code is different.

     this.BeginInvoke((MethodInvoker)delegate

     {

        Console.WriteLine("Writing to console via anonymous method. ");

     }));

gk wrote re: Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on 07-31-2007 9:22 AM

what if InvokeRequired is false?

DoWork is a proc that can be executed by a thread that doesn't need marshling. It doesn't look that elegant anymore. does it?

Another Coding Catastrophe wrote Another Coding Catastrophe
on 04-09-2008 3:59 AM

Pingback from  Another Coding Catastrophe

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Copyright © :: JaysonKnight.com
External Content © :: Respective Authors

Terms of Service/Privacy Policy