Friday, August 3, 2007

Anonymous Functions and Invoking in WPF

At first, I had a little bit of trouble going from multi-threaded WinForms to WPF. The reason is that Invoke changed quite a bit between the two. Here's how to do Invoke in WPF:

First off, for those who don't know, invoke is required when you want to change something for a control or window that is on a different thread than your current one. For example, if you want to Close your window after a timer elapses, you need to send that command back to the Window's thread.

Here's the easy way to do Invoke in your Window, along with the code for the example I just gave:

1delegate void VoidDelegate();
2
3void invokeAndDoAnything()
4{
5 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(delegate()
6 {
7 //Do anything you want to the window in here!
8 }));
9}
10
11void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
12{
13 ((System.Timers.Timer)sender).Stop();
14 //Close the window after this timer is done.
15 //We can just use the Window's close function in the
16 // VoidDelegate, because it happens to take no parameters
17 // and return void.
18 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(Close));
19}


Pretty simple overall, you just need to know the correct syntax to do it. This way you can do multi-threading without worrying about those annoying cross-threaded operation errors, and with anonymous functions, you don't need to clutter up your code for small operations.

1 comments:

Wizard of Ogz said...

Thanks for the tip! It saved me a little headache as I'm starting a new WPF project.

Void delegates are already defined in mscorlib as Action, which means that you could omit the first line of code from your example and replace all instances of new VoidDelegate with new Action.

That said, I think that "Action" is a horribly unclear name and that "VoidDelegate" is much easier to read. I personally do not like to have my code cluttered with delegate type declarations, so I'll stick with Actions for now.