MethodInvoker vs Action for Control.BeginInvoke

哪个更正确,为什么?

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 ,甚至写一个lambdaexpression式?

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

两者同样正确,但Control.Invoke的文档声明:

委托可以是EventHandler的一个实例,在这种情况下,sender参数将包含此控件,而event参数将包含EventArgs.Empty。 委托也可以是MethodInvoker的一个实例,或者其他任何接受void参数列表的委托。 对EventHandler或MethodInvoker委托的调用将比对另一个委托types的调用更快。

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

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

  • 只读MethodInvoker:5664.53(+ 0%)
  • 新方法投资者:5828.31(+ 2.89%)
  • MethodInvoker投射的函数:5857.07(+ 3.40%)
  • 只读操作:6467.33(+ 14.17%)
  • 新行动:6829.07(+ 20.56%)

每次迭代调用一个新的Action

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

在每次迭代时调用一个只读,构造函数, Action

  // 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; } } 

呼叫“新行动”解决scheme的示例:

  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"); } 

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

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

Action在System中定义,而MethodInvoker在System.Windows.Forms中定义 – 使用Action可能会更好,因为它可以移植到其他地方。 您还会发现更多接受Action的地方,而不是MethodInvoker。

但是,该文档确实表示对Control.Invoke()中的EventHandler或MethodInvokertypes的委托的调用将比任何其他types更快。

除了他们在哪个namepsace,我不相信Action和MethodInvoker之间有一个有意义的function差异 – 他们基本上都被定义为:

 public delegate void NoParamMethod(); 

另外,Action有几个重载,允许传入参数 – 它是通用的,所以它们可以是types安全的。

另外每个MSDN:

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

另一方面, Action可能需要4个参数。

但是我不认为MethodInvokerAction之间有任何区别,因为它们都只是简单地封装了一个不包含参数的代表并返回void

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

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

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

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

在大多数情况下,这是一个优先事项,除非您打算重用DoSomething()方法。 此外,匿名函数会将您的作用域variables放在堆上,可能会使其成为一个更昂贵的函数。