Automating the InvokeRequired code pattern Automating the InvokeRequired code pattern multithreading multithreading

Automating the InvokeRequired code pattern


Lee's approach can be simplified further

public static void InvokeIfRequired(this Control control, MethodInvoker action){    // See Update 2 for edits Mike de Klerk suggests to insert here.    if (control.InvokeRequired) {        control.Invoke(action);    } else {        action();    }}

And can be called like this

richEditControl1.InvokeIfRequired(() =>{    // Do anything you want with the control here    richEditControl1.RtfText = value;    RtfHelpers.AddMissingStyles(richEditControl1);});

There is no need to pass the control as parameter to the delegate. C# automatically creates a closure.


UPDATE:

According to several other posters Control can be generalized as ISynchronizeInvoke:

public static void InvokeIfRequired(this ISynchronizeInvoke obj,                                         MethodInvoker action){    if (obj.InvokeRequired) {        var args = new object[0];        obj.Invoke(action, args);    } else {        action();    }}

DonBoitnott pointed out that unlike Control the ISynchronizeInvoke interface requires an object array for the Invoke method as parameter list for the action.


UPDATE 2

Edits suggested by Mike de Klerk (see comment in 1st code snippet for insert point):

// When the form, thus the control, isn't visible yet, InvokeRequired  returns false,// resulting still in a cross-thread exception.while (!control.Visible){    System.Threading.Thread.Sleep(50);}

See ToolmakerSteve's comment below for concerns about this suggestion.


You could write an extension method:

public static void InvokeIfRequired(this Control c, Action<Control> action){    if(c.InvokeRequired)    {        c.Invoke(new Action(() => action(c)));    }    else    {        action(c);    }}

And use it like this:

object1.InvokeIfRequired(c => { c.Visible = true; });

EDIT: As Simpzon points out in the comments you could also change the signature to:

public static void InvokeIfRequired<T>(this T c, Action<T> action)     where T : Control


Here's the form I've been using in all my code.

private void DoGUISwitch(){     Invoke( ( MethodInvoker ) delegate {        object1.Visible = true;        object2.Visible = false;    });} 

I've based this on the blog entry here. I have not had this approach fail me, so I see no reason to complicate my code with a check of the InvokeRequired property.

Hope this helps.