Using ISynchronizeInvoke to update your UI safely from another Thread.

If you are still using .NET threads to do multi-threading in your applications (compared to the Task Parallel Library or something else), then it is often a mistake of developers on how they update their UI thread. First off, stay the heck away from CheckForIllegalCrossThreadCalls. If you want your application to have unpredictable behavior, throw intermittant exceptions, and have loads of problems then go right ahead. If you want to do things right, read on.

In the early days of .NET, it was common to implement the Invoke pattern which is actually more work than needed. Most if not all WinForms controls for example implement an interface called ISynchronizeInvoke. You can use this to easily update your controls safely from another thread, in a single line of code. Here is the implementation:

//-----------------------------------------------------------------------------
// <copyright file="ISynchronizedInvoke.cs" company="DCOM Productions">
//     Copyright (c) DCOM Productions.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------

namespace YourApplication {
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;

    /// <summary>
    /// Helper class that allows synchronized invoking to be performed in a single line of code.
    /// </summary>
    internal static class SynchronizedInvoke {
        /// <summary>
        /// Invokes the specified action on the thread that the specified sync object was created on.
        /// </summary>
        public static void Invoke(ISynchronizeInvoke sync, Action action) {
            if (!sync.InvokeRequired) {
                action();
            }
            else {
                object[] args = new object[] { };
                sync.Invoke(action, args);
            }
        }
    }
}

This is just a helper class I usually include in all my WinForms projects as SynchronizedInvoke.cs. But the call is very simple. Let’s say you have a thread that runs a method called “ThreadWork” and you want to set the value of a progress bar you’ve named ‘uxProgressBar’ to 100 at the end of the method.

private void ThreadWork() {
    // Do some work on a thread
    SynchronizeInvoke.Invoke(uxProgressBar, () => uxProgressBar.Value = 100);
}

The key is the first parameter, also called the ‘sync’, is the object you want to invoke on, and the second is just an anonymous method (you can also specify an actual Action). There’s really nothing more to it, but you should also give a read to the article I wrote on using the Task Parallel Library titled ‘Writing thread-safe event handlers with the Task Parallel Library in .NET 4.0‘ which in my opinion is a better way to perform threaded operations and UI updates.

Leave a Reply