Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using MethodInvoker without Invoke

I am writing GUI applications for some time now and one thing I always use are MethodInvoker + lambda functions to do cross-thread access.

From the examples I find I always see stuff like this:

Version 1

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

However this leads to code-duplication --> major baddie to me.

So what's wrong with this?

Version 2

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

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

Now I have the functionality bundled in one variable and call it with Invoke or as a function pointer when appropriate. Is version 2 worse performance-wise? Or is i bad practice to use anonymous functions for this?

like image 743
Nebula Avatar asked Dec 08 '22 22:12

Nebula


2 Answers

Nothing's wrong with it... but you can add an extension method to make it all somewhat 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 neater :)

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

Note that even if you don't want to do that, you can still make your variable declaration simpler in your existing code:

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

That's one benefit of using a separate variable - you don't need the new MethodInvoker bit to tell the lambda expression what type of delegate you want...

like image 143
Jon Skeet Avatar answered Dec 28 '22 22:12

Jon Skeet


Is version 2 worse performance-wise? Or is i bad practice to use anonymous functions for this?

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

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

and then:

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

or simply use a BackgroundWorker which will automatically execute all callbacks (such as RunWorkerCompleted and ProgressChanged) on the main UI thread so that you don't need to check for InvokeRequired.

like image 40
Darin Dimitrov Avatar answered Dec 28 '22 21:12

Darin Dimitrov