Project Description
ThreadSafeControls is a C# project that greatly simplifies the process of transitioning Windows Forms applications to a multithreaded environment by providing a quick and intuitive API for thread-safe GUI updates.

Overview
Often, when developing Windows Forms applications, rookie developers will write code like this:

private void button1_Click(object sender, EventArgs e) {
    label1.Text = "Loading up...";
    // lots of code
    
    label1.Text = "Doing some additional work...";
    // lots more code
    
    label1.Text = "Finished!";
}

As any developer with Windows Forms experience knows, of course, the above code is flawed in several ways. First, the lines that change the text displayed by label1 have no visible effect, since the form will not repaint itself until button1_Click terminates. Second, since this method is being run on the same thread responsible for GUI updates, the GUI will freeze while the above code is running. Finally, if the developer maintaining this code decides to do things the right way and split the logic in button1_Click off to a separate thread (e.g., using a BackgroundWorker), then each of the lines that update label1 will suddenly result in an illegal cross-thread operation.

Traditionally, there are "right" ways and "wrong" ways to solve this problem. One "right" way would be to separate the business logic of the application (on a separate thread) from the UI presentation, most likely refactoring the above "quick and dirty" code into something more elegant. This would typically mean updating the UI through some form of thread-safe signaling, for instance by handling the BackgroundWorker.ProgressChanged event. One "wrong" way would be to simply sprinkle a few calls to Application.DoEvents into the above method. This would get label1 to update, but it wouldn't solve the problem of the GUI freezing.

An even worse "wrong" solution would be to split the above code off to a separate thread and set Control.CheckForIllegalCrossThreadCalls = false. This would allow the GUI to remain responsive, but it would also open up the sinister possibility of memory corruption and the application completely crashing!

Notice that there is a substantial difference in the amount of work required to fix the above code the "right" way (refactoring) versus the "wrong" way (a few extra lines of code). While no one wants to write hacky code, sometimes refactoring simply isn't worth the effort. For this reason, developers faced with the task of fixing code like this often make a compromise, using the Control.Invoke method in tandem with the Control.InvokeRequired property, like so:

if (label1.InvokeRequired)
    Action textUpdate = () => label1.Text = "Loading up...";
    label1.Invoke(textUpdate);
else
    label1.Text = "Loading up...";

The idea behind the ThreadSafeControls project is simple: to eliminate the need for boilerplate code like the above snippet, while providing an easy and intuitive API for writing code that provides the same level of thread-safety. This allows developers to deal with scenarios like button1_Click above quickly, cleanly, and in a completely thread-safe manner.

To get an idea of just how easy the library is to use, take a look at how the above scenario might be resolved using the ThreadSafeControls API:

// assume code is now running on a separate thread

// this is the only line you need to add!
var threadSafeLabel = label1.AsThreadSafe();

threadSafeLabel.Text = "Loading up...";
// lots of code

threadSafeLabel.Text = "Doing some additional work...";
// lots more code

threadSafeLabel.Text = "Finished!";

That's all there is to it! For greater detail (though there honestly isn't much more you need to know), take a look at the Documentation.

Last edited May 4, 2010 at 12:59 AM by danieltao, version 4