Cleaning up code littered with InvokeRequired

Erik Forbes picture Erik Forbes · Oct 6, 2010 · Viewed 16.9k times · Source

I know that when manipulating UI controls from any non-UI thread, you must marshal your calls to the UI thread to avoid issues. The general consensus is that you should use test InvokeRequired, and if true, use .Invoke to perform the marshaling.

This leads to a lot of code that looks like this:

private void UpdateSummary(string text)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => UpdateSummary(text)));
    }
    else
    {
        summary.Text = text;
    }
}

My question is this: can I leave out the InvokeRequired test and just call Invoke, like so:

private void UpdateSummary(string text)
{
    this.Invoke(new Action(() => summary.Text = text));
}

Is there a problem with doing this? If so, is there a better way to keep the InvokeRequired test while not having to copy and paste this pattern all over the place?

Answer

John Gietzen picture John Gietzen · Oct 6, 2010

Well how about this:

public static class ControlHelpers
{
    public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : ISynchronizeInvoke
    {
        if (control.InvokeRequired)
        {
            control.Invoke(new Action(() => action(control)), null);
        }
        else
        {
            action(control);
        }
    }
}

Use it like this:

private void UpdateSummary(string text)
{
    summary.InvokeIfRequired(s => { s.Text = text });
}