Towards cleaner code, a C# Async. Helper for GUI (Pt 3 of 3)
Posted by Nicholas Brookins on 27 September, 2008// Threading and User Interfaces
When doing GUI development on Windows you must very careful what thread you access a form or control from. Hopefully most Windows Forms developers know this by now, but in the early versions of the framework it could be a sneaky issue. As of .NET 2.0 they were kind enough to immediately cause an exception when a control was accessed from the wrong thread - forcing you to deal with it now instead of trying to figure out why you randomly get exceptions like this 6 weeks after deploying your application: 
I wont delve much in to why this is necessary, there are plenty of explanations on the subject. The short story is that in .NET there is still a message loop that is running on the thread your form was run from, access from any other thread just isn’t thread-safe - you can’t use locking because it would block the user interface.
So let’s append the Async helper static class that we worked on in parts 1 and 2, giving it the ability to schedule tasks on the UI thread. This will go even further towards making an app cleaner and more maintainable.
UPDATE: This post is now an article on CodeProject.
// The old way of doing things.
Let’s say we want to update a TextBox in our application. Following with tradition I’ll show a few conventional ways to accomplish this, and then how we can do better. Here is what we are trying to do:
private void UpdateText(string myString){
textBox1.Text = myString;
}
Simple as can be. Problem is when we want to run it from anywhere in our code. One way is to check if an invoke is required each time we run it. In this case I’m again using anonymous methods to keep things as clean as possible.
// ... //
// ask the control if we are on its UI thread
if(textBox1.InvokeRequired){
//we are not, so an invoke is required.
textBox1.Invoke(delegate{UpdateText("This is text");});
}else{
//we are on the UI thread, we can directly modify the control
UpdateText("This is text");
}
// ... //
A safer way is to build the invoke into the method itself. Note that this time I am using BeginInvoke, same concept but it does not block - it runs the task asynchronously.
private void SafeUpdateText(string myString){
if(textBox1.InvokeRequired){
//Invoke into this same method, but this time on the correct thread.
textBox1.BeginInvoke(delegate{UpdateText(myString);});
return; //important, so we don't fall through
}
//this only runs if the above check says an invoke is not required.
textBox1.Text = myString;
}
Hopefully that isn’t too confusing. If the Invoke is required we invoke our own method recursively, knowing that it will be on the right thread on the next time through. This isn’t too bad, but it can be a serious pain to make a method for every operation you need to do - once again its more things to remember and maintain, and more bloat for larger applications.
// The new method: Async.UI(…);
So know let’s fix up our Async class to make this whole process easier. I decided to make a separate method for this, ‘Do()‘ had enough overloads as it was and I wanted it to be very clear at a glance whether the task was UI related.
I’ll start with usage. Instead of all of the above, we can now do this:
//Method prototype: public static AsyncRes UI(Dlg d, Control c, bool asynchronous);
Async.UI(delegate { textBox1.Text = "This is way easier!"; }, textBox1, true);
Once again, something that might have needed a separate method and 5 to 10 lines of code, can know be distilled into a quick single method that takes care of the details for us. Let’s check see what those arguments are.
Our first argument is a delegate, same as we’ve done before - it can be an actual delegate instance, an anonymous method as above, or even a method without a parameter which .NET will silently wrap into a delegate.
The second parameter is the Control we’d like to invoke with. It can be the control you are accessing, our any of it’s parent controls/forms. Of course in the method you pass, you can modify as many controls as you like, provided they are all from the same form / UI thread.
Third is a bool that if true, tells the method to use BeginInvoke to make the call non-blocking. Otherwise the caller will block while the UI thread finds time to run your task.
// I, for one, welcome our new UI method overloads.
We have three more overloads with more and more options, first here are the prototypes:
// This re-introduces our ReentraceMode option, for thread safety and more control.
public static AsyncRes UI(Dlg d, Control c, bool async, ReenteranceMode rMode)
// Now with the ability to grab a return value for you
public static AsyncRes UI(DlgR d, bool getRetVal, Control c, bool async);
// Pass a state object that is returned on an EndInvoke
public static AsyncRes UI(Dlg d, Control c, object state, bool async, ReenteranceMode rMode);
// And the last one, with all of the above.
public static AsyncRes UI(DlgR d, bool getRetVal, Control c, object state,
bool async, ReenteranceMode rMode);
Got all that? It should all be pretty straight-forward. Now I’ll demonstrate using the last one with a return value.
// ... //
AsyncRes result = Async.UI(
//make sure the delegate/method returns a value:
delegate { return textBox1.Text; },
true, //yes, we want to get the return value
myForm, //the control to invoke on
null, //the state object, we don't need to track anything.
true, //invoke asynchronously?
ReenteranceMode.Allow); //don't worry about thread safety in this case.
// .... do other things ... //
// now make sure the task above has completed..
result.AsyncWaitHandle.WaitOne();
//and use the value
Console.WriteLine("The textbox says: " + result.ReturnValue);
// ... //
That’s about as complicated as it gets now; even the most advanced usage of the new class is simpler than invoking the most basic UI tasks without it. The call to WaitOne is only needed because we chose to invoke asynchronously - we need to make sure it has completed or our value might be null. If we had passed a false to the async parameter the call would have blocked and the value would immediately be guaranteed to be there.
// The code that makes it happen.
This functionality has been added to the same Async class we’ve already been working with, and it makes use of much of the same code: all of our UI methods simply call the Do method internally, which has been expanded slightly. Here is the new signature of the Do method, along with a new blurb for handling UI:
// The private master Do method now also takes a control.
private static AsyncRes Do(DlgR dr, Dlg d, bool getRetVal, object state,
bool tryThreadPool, ReenteranceMode rMode, Control control, bool async) {
// .. In the first part we still set up our delegate the same way as before //
if(control!=null) {
res.control = control;
res.result = AsyncAction.ControlInvoked;
if (!async) {
if (!control.InvokeRequired) {
res.completedSynchronously = true;
dlg();
} else {
control.Invoke(dlg);
}
}else {
control.BeginInvoke(dlg);
}
return res;
}
// don't catch any errors; if this fails
// we don't want it to continue below and get invoked in some other way
// .. the rest of the method, where we use thread or the threadpool
// .. only happens if the control was null, meaningth ecall was not UI related.
We were able to add quite a bit of functionality to this handy class, with only a few lines of code! The only other change is adding all of the UI overloads, each one simply calls Do with various parameters:
public static AsyncRes UI(Dlg d, Control c, bool async) {
return Do(null, d, false, null, false, ReenteranceMode.Allow, c, async);
}
public static AsyncRes UI(DlgR d, bool getRetVal, Control c, object state,
bool async, ReenteranceMode rMode) {
return Do(d, null, getRetVal, state, false, rMode, c, async);
}
// .. and so on .. //
That’s all there is to it. Of course now we have some updated source code to share with you. The new zip file is the source in a VS2005 project, and the Async2.cs file has the entire source code for the previous posts, along with these new updates; now up to a 400 lines.
Again, let me know if you have any problems, comments, suggestions, questions, compliments, or threats of bodily harm - I’ll take them in stride.
*Coming in future posts of this series: Expanding this async concept into timers for recurring tasks, a handy stop watch, a throttling utility, and configuration file handling.
![]()

Subscribe to Posts
Subscribe by Email
October 8th, 2008 a.t 11:26 am
Very nice… It’s the best code sample in that matter I could find that does not involve Code.Emit
But now… Here is what I think is missing:
* Can you add the “needed” call to EndInvoke? Still without blocking of course.
* Can I have parameters for the methods I call
* Can I have a specific delegate for each method instead of the generic delegate you are using?
October 9th, 2008 a.t 3:56 am
OK, had some time to think and I have to admit that point 2 and 3 are not needed. I didn’t understand how I should be using your stuff. Because of the anonymous delegate, you don’t need to pass any parameters because you share the same local context. Excellent stuff.
I handled the endinvoke in a thread I’m launching myself. I would be interested to see if you have an idea on how to solve this…
October 9th, 2008 a.t 9:20 am
Hi Jonx, thanks for the feedback. Yes, the anonymous methods are great stuff. I’ve gotten similar suggestions for an EndInvoke - I plan to update the class with that capability and a few other goodies over the next few days, keep your eye out for another post on the series!
October 13th, 2008 a.t 4:10 pm
Thanks!
This is very interesting, but I have no idea how to use this with WPF instead of Winforms.
If you could find the time, it would be really great if you could provide an example for WPF using probably Dispatcher.InvokeReqireq, Dispatcher.BeginInvoke.
Maybe anybody else has already tried to adapt this for WPF?
October 15th, 2008 a.t 9:38 am
Host, I don’t see why there must be a difference between winforms and wpf. It should work the same. That said, I don’t use wpf…
Nicholas, Note that you can’t BeginInvoke on a control that is .Created == false. This is the case when you try to .Do from a constructor instead of doing it only after the control has been loaded. I added the test to report it to the users to force them to only invoke when they are allowed to… that said. I’ll added your feed to my reader
October 16th, 2008 a.t 7:38 am
Horst - I haven’t yet used this with WPF, the project it is used in is still on .NET 2.0. I do have plans to update it soon, and I’ll certainly post the new source.
Jonx - that’s a good find, I’ll include that check in my next version - thanks for the note.
It’ll be a little bit of a wait for the next post, I’m in the middle of a move - driving from Michigan to San Diego, Ca!
April 6th, 2009 a.t 4:09 pm
In your blog you mention some nice features that you’ll be working on. Just currious when we can expect a new release? Great work thus far.
May 9th, 2009 a.t 5:27 am
Good article… looking forward to the next pieces. I’ve been researching these topics for days to see the good/bad and this one is very straight forward with good examples and writing style… thanks!
July 18th, 2010 a.t 6:56 pm
Just got my samsung delve yesterday and gotta say i’m lovin it. I’ve previously browsed this website very a bit and i’m basically applying my samsung delve as a modem to kind this lol. I am a U.S. cellular consumer and we have one of thier aircards for internet but i think this telephone is more quickly, I did do the signal strenght hack also and would seem to be workin pretty well.