Nebula
Nebula

Reputation: 1057

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?

Upvotes: 4

Views: 6100

Answers (3)

jhyap
jhyap

Reputation: 3837

Another practice on doing it:

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

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1499800

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...

Upvotes: 10

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

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.

Upvotes: 2

Related Questions