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个参数。
但是我不认为MethodInvoker和Action之间有任何区别,因为它们都只是简单地封装了一个不包含参数的代表并返回void
如果你看他们的定义,你会看到这个。
public delegate void MethodInvoker(); public delegate void Action();
顺便说一句,你也可以写你的第二行。
Control.BeginInvoke(new MethodInvoker(DoSomething), null);
在大多数情况下,这是一个优先事项,除非您打算重用DoSomething()方法。 此外,匿名函数会将您的作用域variables放在堆上,可能会使其成为一个更昂贵的函数。