free geoip Using Anonymous Methods For Control.Invoke/Control.BeginInvoke - Jayson's Blog - jaysonKnight.com
jaysonKnight.com
A conduit to the voices inside my head.
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 Wed, Feb 14 2007 5:35 PM by Jayson Knight
comments powered by Disqus

Comments

DotNetKicks.com wrote Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on Wed, Feb 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 Fri, Feb 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 Tue, Jul 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 Wed, Apr 9 2008 3:59 AM

Pingback from  Another Coding Catastrophe

nummersex wrote re: Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on Wed, Jan 21 2009 11:18 AM

Hey.

Thanks for the info.

I thought maybe you would wanna know that you can use a lamda expression also, like this:

this.BeginInvoke(new MethodInvoker(() => label1.Text = numberOfTimesRunned.ToString()));

That maybe just applies to vs 2008 (.net 3.5) but anyways.

Hemant wrote re: Using Anonymous Methods For Control.Invoke/Control.BeginInvoke
on Thu, Aug 5 2010 10:50 PM

Nice post.

Actually we can also use ThreadStart delegate instead of MethodInvoker

     this.BeginInvoke((ThreadStart)delegate

    {

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

    }));

Regards,

Hemant Shelar  

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

Terms of Service/Privacy Policy