使用MethodInvoker没有调用(Using MethodInvoker without In

2019-07-30 23:36发布

我现在有一段时间了编写GUI应用程序中有一件事我一直用的都是MethodInvoker + lambda函数做跨线程访问。

从例子中我发现,我总是看到这样的东西:

第1版

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

然而,这会导致代码的重复 - >大坏蛋给我。

那么,有什么问题呢?

第2版

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

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

现在我有以下功能:在一个变量捆绑与调用或函数指针在适当的时候调用它。 为2版性能越差明智? 或者是我不好的做法,使用匿名函数呢?

Answer 1:

没有什么地方错了...但你可以添加一个扩展方法,使这一切有点更好:

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

然后,你可以这样写:

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

更整洁:)

有一个从创建委托时,你并不需要一个很轻微的性能缺陷,但它几乎肯定微不足道-专注于编写干净的代码。

请注意,即使你不想做,你仍然可以使你的变量声明简单在现有的代码:

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

这是使用一个独立的变量的一个好处-你不需要new MethodInvoker位来告诉你想要什么类型的委托的lambda表达式...



Answer 2:

为2版性能越差明智? 或者是我不好的做法,使用匿名函数呢?

没有第2版比较好,不用担心它的性能问题。 而不是使用匿名函数,你也可以定义一个方法:

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

然后:

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

或者简单地用一个BackgroundWorker的 ,它会自动执行所有回调(如RunWorkerCompletedProgressChanged ,这样你就不需要检查主UI线程) InvokeRequired



Answer 3:

在做另一种做法:

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


文章来源: Using MethodInvoker without Invoke