哪个更正确,为什么?
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
似乎是出于特定目的。这有什么不同吗?
答案 0 :(得分:74)
两者都同样正确,但Control.Invoke
的文档指出:
委托可以是。的实例 EventHandler,在这种情况下发件人 参数将包含此控件, 并且event参数将包含 EventArgs.Empty。代表也可以 是MethodInvoker的一个实例,或者 任何其他代表无效的代表 参数列表。打电话给 EventHandler或MethodInvoker委托 会比打电话给另一个更快 代表的类型。
所以MethodInvoker
将是一个更有效的选择。
答案 1 :(得分:25)
对于每个解决方案,我运行131072(128 * 1024)次迭代(在一个单独的线程中)。 VS2010性能助手给出了这样的结果:
在每次迭代时调用新的操作
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"));