MethodInvoker与Control.BeginInvoke的Action

时间:2009-07-22 19:47:12

标签: c# .net delegates invoke

哪个更正确,为什么?

Control.BeginInvoke(new Action(DoSomething), null);

private void DoSomething()
{
    MessageBox.Show("What a great post");
}

Control.BeginInvoke((MethodInvoker) delegate { 
    MessageBox.Show("What a great post");
}); 

我觉得我在做同样的事情,所以什么时候适合使用MethodInvoker vs Action,甚至写一个lambda表达式?

编辑:我知道写一个lambda与Action之间并没有什么区别,但MethodInvoker似乎是出于特定目的。这有什么不同吗?

7 个答案:

答案 0 :(得分:74)

两者都同样正确,但Control.Invoke的文档指出:

  

委托可以是。的实例   EventHandler,在这种情况下发件人   参数将包含此控件,   并且event参数将包含   EventArgs.Empty。代表也可以   是MethodInvoker的一个实例,或者   任何其他代表无效的代表   参数列表。打电话给   EventHandler或MethodInvoker委托   会比打电话给另一个更快   代表的类型。

所以MethodInvoker将是一个更有效的选择。

答案 1 :(得分:25)

对于每个解决方案,我运行131072(128 * 1024)次迭代(在一个单独的线程中)。 VS2010性能助手给出了这样的结果:

  • 只读MethodInvoker:5664.53(+ 0%)
  • New MethodInvoker:5828.31(+2.89%)
  • MethodInvoker中的函数转换:5857.07(+ 3.40%)
  • 只读操作:6467.33(+ 14.17%)
  • 新动作:6829.07(+ 20.56%)

在每次迭代时调用新的操作

    private void SetVisibleByNewAction()
    {
        if (InvokeRequired)
        {
            Invoke(new Action(SetVisibleByNewAction));
        }
        else
        {
            Visible = true;
        }
    }

在每次迭代时调用只读,内置构造函数操作

    // private readonly Action _actionSetVisibleByAction
    // _actionSetVisibleByAction= SetVisibleByAction;
    private void SetVisibleByAction()
    {
        if (InvokeRequired)
        {
            Invoke(_actionSetVisibleByAction);
        }
        else
        {
            Visible = true;
        }
    }

在每次迭代时调用新的 MethodInvoker

    private void SetVisibleByNewMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
        }
        else
        {
            Visible = true;
        }
    }

在每次迭代时调用只读,内置构造函数 MethodInvoker

    // private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker 
    // _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
    private void SetVisibleByMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(_methodInvokerSetVisibleByMethodInvoker);
        }
        else
        {
            Visible = true;
        }
    }

在每次迭代时调用 MethodInvoker 中的函数

    private void SetVisibleByDelegate()
    {
        if (InvokeRequired)
        {
            Invoke((MethodInvoker) SetVisibleByDelegate);
        }
        else
        {
            Visible = true;
        }
    }

呼叫"新动作"解决方案:

    private void ButtonNewActionOnClick(object sender, EventArgs e)
    {
        new Thread(TestNewAction).Start();
    }

    private void TestNewAction()
    {
        var watch = Stopwatch.StartNew();
        for (var i = 0; i < COUNT; i++)
        {
            SetVisibleByNewAction();
        }
        watch.Stop();
        Append("New Action: " + watch.ElapsedMilliseconds + "ms");
    }

答案 2 :(得分:9)

我更喜欢使用lambdas和Actions / Funcs:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));

答案 3 :(得分:4)

Action在System中定义,而MethodInvoker在System.Windows.Forms中定义 - 您可能最好使用Action,因为它可以移植到其他地方。您还可以找到更多接受Action作为参数而不是MethodInvoker的地方。

但是,文档确实表明对Control.Invoke()中EventHandler或MethodInvoker类型的委托的调用将比任何其他类型更快。

除了它们所处的名称之外,我不认为Action和MethodInvoker之间存在有意义的功能区别 - 它们基本上都被定义为:

public delegate void NoParamMethod();

顺便说一下,Action有几个允许传入参数的重载 - 它是通用的,因此它们可以是类型安全的。

答案 4 :(得分:3)

同样根据MSDN:

MethodInvoker 提供了一个简单的委托,用于调用带有void参数列表的方法。在调用控件的Invoke方法时,或者当您需要一个简单的委托但不想自己定义一个委托时,可以使用此委托。

另一方面,行动最多可以使用4个参数。

但我认为 MethodInvoker Action 之间没有任何区别,因为它们都只是封装了一个不占用paremter并返回的委托空隙

如果你看一下他们的定义,你就会看到这个。

public delegate void MethodInvoker();
public delegate void Action();

顺便说一句,你也可以把你的第二行写成。

Control.BeginInvoke(new MethodInvoker(DoSomething), null);

答案 5 :(得分:2)

在大多数情况下,这是一个首选问题,除非您打算重用DoSomething()方法。此外,匿名函数会将您的范围变量放在堆上,可能会使它成为一个更昂贵的函数。

答案 6 :(得分:0)

不要忘记以某种方式检查控制是否可用,以避免在结束时出现错误。

if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));