Search The Blog
My Books

New:

My Songs

 

The Art of Unit Testing

Buy PDF or Print book at Manning

Buy on Amazon

Latest Posts
from 5whys.com
Twitter: @RoyOsherove
About this site

TDD in .NET Online Course

TDD and BDD in Ruby Online Course

 

Subscribe!

This site aims to connect all the dots of my online activities - from tools, books blogs and twitter accounts, to upcoming conferences, engagements and user group talks.

« The Next Regex Regulator | Main | The Reanimator - Visualize How the Regex Engine Works »
Wednesday
Mar012006

The 3 ways to create a Thread-Safe GUI with .NET 2.0, with one clear winner.

With .NET 2.0 and with the new "anonymous delegates" feature in C#, doing multi threaded responsive GUIs is now easier. In fact, you get multiple choices on how to accomplish this task. But which choice is the best? and what does "best" really mean? more elegant? faster? more readable? all of the above?

Here's a little scenario for you. Assume there is a method that displays a string on the GUI, but may be called by a different thread than the GUI. The method has only a single string parameter. here are three versions of how you can implement this method and keep it thread safe. The last one is my favorite.

First, I'll declare two "generic" delegates. Each one is used in a different version of the method.

 delegate void Func<T>(T t);
private void displayError(string message)
        {
            
if (InvokeRequired)
            {
                Func<
string> del displayError;
                
Invoke(del, message);
                return;
            
}
            errorDisplay.Show(message)
;
        
}
This version uses a generic delegate which takes a string argument, then if Invoke is needed, it "Invokes" the delegate passing in the string argument. Note that passing in the string is not a strongly typed operation and may result in runtime errors if we make a mistake in the parameter order for example. That's why I don't like this version at all. But it's the most commonly used that I've seen, which is why I'm writing this.


delegate void Func();
        private void displayError1(string message)
        {
            
if (InvokeRequired)
            {
                Func del 
= delegate { displayError1(message)};
                
Invoke(del);
                return;
            
}
            errorDisplay.Show(message)
;
        
}
        
This version uses a delegate with no parameters, and uses the "delegate" directive to create a delegate that calls the same method with the "message" parameter. Notice how lovely it is to be able to use a local scoped variable such as "message" in out delegate. It makes life much simpler because now all we ever need to do is just use one delegate signature for all of our thread-safe GUI work. This version is much better than the previous one because it's type-safe. We can't make a mistake in parameter order or type, or we'll have a build error. But this version is still not as elegant as I would like.


        private void displayError2(string message)
        {
            Func del 
= delegate
                
{
                    errorDisplay.Show(message)
;
                
};
            
Invoke(del);
        
}
This version uses the delegate directive to actually create the full functionality of our method. Notice that we *always* invoke the code in here using the "Invoke" method which is thread-safe, even if this is not required. Also note how much less code we have to write here, and that we always use the same delegate signature to accomplish this. Not only that, in contrast to the other two implementations, we only write the calling code once inside the delegate, and not another time outside of it which can lead to maintenance problem due to duplication. This method, to me, is the most elegant and readable. I don't really care about one extra call to the "Invoke" method, since this method is GUI related, and obviously is called after a long operation which was async. 10 nano seconds more or less won't matter one bit. This is the method I'd encourage you to use, even though it seems a bit un-orthodox at first, it is clearly the simplest of the three, with less code, less duplication and more readability.


Colorized by: CarlosAg.CodeColorizer

Unfortunately, all three methods require you to use C#, since anonymous delegates are not present in VB.NET yet.

Thoughts?

PrintView Printer Friendly Version

Reader Comments (1)

Hey came across your blog while searching through google for making thread safe calls in VB.NET.... above methods are cool...but can u suggest any method to use in "VB.NET" and NOT C# ?? I'm doing a project on Email Manager and need to create a Threading module for same. Thanx in advance.

March 2, 2011 | Unregistered CommenterJJ

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
Web Analytics