Using the invoker method without calling

I have been writing GUI applications for some time, and one thing that I always use is the MethodInvoker + lambda functions for performing cross-thread access.

From the above examples, I always see such things:

Version 1

if (InvokeRequired) { Invoke(new MethodInvoker(() => { Label1.Text = "Foobar"; }); } else { Label1.Text = "Foobar"; } 

However, this leads to code duplication → to a large attacker.

So what's wrong with that?

Version 2

 MethodInvoker updateText = new MethodInvoker(() => { Label1.Text = "Foobar"; }); if (InvokeRequired) { Invoke(updateText); } else { updateText(); } 

Now I have the functionality associated with a single variable, and call it with Invoke or as a function pointer, when necessary. Is version 2 worse in performance? Or am I using anonymous functions poorly for this?

+4
source share
3 answers

There is nothing wrong with that ... but you can add an extension method to make it a little nicer:

 public static void InvokeIfNecessary(this Control control, MethodInvoker action) { if (control.InvokeRequired) { control.Invoke(action); } else { action(); } } 

Then you can write:

 this.InvokeIfNecessary(() => Label1.Text = "Foobar"); 

Much neat :)

There is a slight performance drawback from creating a delegate when you don't need it, but it is almost certainly insignificant - focus on writing clean code.

Note that even if you do not want to do this, you can still make variable declaration easier in your existing code:

 MethodInvoker updateText = () => Label1.Text = "Foobar"; 

This is one of the advantages of using a separate variable - you don't need the new MethodInvoker bit to tell the lambda expression what kind of delegate you want ...

+10
source

Is version 2 worse in performance? Or am I using anonymous functions poorly for this?

No version 2 is better, don't worry about performance issues. Instead of using an anonymous function, you can also define a method:

 public void SetLabelTextToFooBar() { Label1.Text = "Foobar"; } 

and then:

 if (InvokeRequired) { Invoke(SetLabelTextToFooBar); } else { SetLabelTextToFooBar(); } 

or just use BackgroundWorker , which will automatically execute all callbacks (e.g. RunWorkerCompleted and ProgressChanged ) in the main thread UI so you don't have to check InvokeRequired .

+2
source

Another practice:

 Invoke((MethodInvoker)delegate { Label1.Text = "Foobar"; }); 
+2
source

All Articles