Using C# 3.0 Extensions Methods to Simplify WinForms Thread Marshalling

Most folks know by now that if you don’t call a WinForms control method on the same thread that created it, you are asking for trouble.  In fact on .NET 2.0 the WinForms team did the right thing in throwing an InvalidOperationException if you call a control from a different thread than which it was created.  There a few thread safe members which include InvokeRequired and Invoke.  In the past we used a pattern like so for methods that could be called by a different thread and the method itself would handle the thread marshalling e.g.:

private delegate void UpdateProgressHandler(int percentComplete);
private void UpdateProgress(int percentComplete) {
    if (InvokeRequired) {
        UpdateProgressHandler del = UpdateProgress;
        this.Invoke(del, percentComplete);
        return;
    } 
    _progressBar.Value = percentComplete;
}   

Ido Samuelson points a way to simplify this using C# 3.0 extension methods which is really pretty clever.  I recommend that you read his blog post here.  I modified his approach to eliminate the UpdateProgress call from the lambda expression.  Here’s my approach:

public static class ControlExtentions {
    public delegate void InvokeHandler(); 

    public static void SafeInvoke(this Control control, InvokeHandler handler) {
        if (control.InvokeRequired) {
            control.Invoke(handler);
        }
        else {
            handler();
        }
    }
}

private void UpdateProgress(int percentComplete)
{
    this.SafeInvoke(() =>
    {
           _progressBar.Value = percentComplete;
    });
}   

Now if my method were more complex than a few lines then I would probably use Ido’s approach.  Having a bunch of code in a lambda makes me a bit nervous – perhaps irrationally so.

About these ads
This entry was posted in Software Development. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s