C# Control.BeginInvoke 的 MethodInvoker 与 Action
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1167771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MethodInvoker vs Action for Control.BeginInvoke
提问by Mike_G
Which is more correct and why?
哪个更正确,为什么?
Control.BeginInvoke(new Action(DoSomething), null);
private void DoSomething()
{
MessageBox.Show("What a great post");
}
or
或者
Control.BeginInvoke((MethodInvoker) delegate {
MessageBox.Show("What a great post");
});
I kinda feel like I am doing the same thing, so when is the right time to use MethodInvoker
vs Action
, or even writing a lambda expression?
我有点觉得我在做同样的事情,那么什么时候使用MethodInvoker
vsAction
甚至编写 lambda 表达式的合适时机?
EDIT:I know that there isn't really much of a difference between writing a lambda vs Action
, but MethodInvoker
seems to be made for a specific purpose. Is it doing anything different?
编辑:我知道编写 lambda 和 lambda 之间没有太大区别Action
,但MethodInvoker
似乎是为特定目的而制作的。它有什么不同吗?
采纳答案by Jon Skeet
Both are equally correct, but the documentation for Control.Invoke
states that:
两者都同样正确,但文档Control.Invoke
说明:
The delegate can be an instance of EventHandler, in which case the sender parameter will contain this control, and the event parameter will contain EventArgs.Empty. The delegate can also be an instance of MethodInvoker, or any other delegate that takes a void parameter list. A call to an EventHandler or MethodInvoker delegate will be faster than a call to another type of delegate.
委托可以是 EventHandler 的实例,在这种情况下,sender 参数将包含此控件,而 event 参数将包含 EventArgs.Empty。委托也可以是 MethodInvoker 的实例,或任何其他采用 void 参数列表的委托。调用 EventHandler 或 MethodInvoker 委托比调用其他类型的委托要快。
So MethodInvoker
would be a more efficient choice.
所以MethodInvoker
会是一个更有效的选择。
回答by Yuriy Faktorovich
It is a matter of preference in most cases, unless you intend to reuse the DoSomething() method. Also the anonymous functions will place your scoped variables on the heap, might make it a more expensive function.
大多数情况下这是一个偏好问题,除非您打算重用 DoSomething() 方法。此外,匿名函数会将您的作用域变量放在堆上,可能会使其成为一个更昂贵的函数。
回答by Stan R.
Also per MSDN:
同样根据 MSDN:
MethodInvokerprovides a simple delegate that is used to invoke a method with a void parameter list. This delegate can be used when making calls to a control's Invoke method, or when you need a simple delegate but do not want to define one yourself.
MethodInvoker提供了一个简单的委托,用于调用带有 void 参数列表的方法。当调用控件的 Invoke 方法时,或者当您需要一个简单的委托但不想自己定义一个委托时,可以使用此委托。
an Actionon the other hand can take up to 4 parameters.
另一方面,一个Action最多可以接受 4 个参数。
But I don't think there is any difference between MethodInvokerand Actionas they both simply encapsulate a delegate that doesn't take a paremter and returns void
但是我认为MethodInvoker和Action之间没有任何区别,因为它们都只是封装了一个不带参数并返回void的委托
If you look at their definitions you'll simply see this.
如果你看一下他们的定义,你就会明白这一点。
public delegate void MethodInvoker();
public delegate void Action();
btw you could also write your second line as.
顺便说一句,您也可以将第二行写为。
Control.BeginInvoke(new MethodInvoker(DoSomething), null);
回答by LBushkin
Action is defined in System, while MethodInvoker is defined in System.Windows.Forms - you may be better off using Action, since it is portable to other places. You will also find more places that accept Action as a parameter than MethodInvoker.
Action 在 System 中定义,而 MethodInvoker 在 System.Windows.Forms 中定义 - 您最好使用 Action,因为它可以移植到其他地方。您还会发现接受 Action 作为参数的地方比 MethodInvoker 多。
However, the documentation does indicate that calls to delegates of type EventHandler or MethodInvoker in Control.Invoke() will be faster than any other type.
但是,文档确实表明,在 Control.Invoke() 中调用 EventHandler 或 MethodInvoker 类型的委托将比任何其他类型都快。
Aside from which namepsace they are in, I don't believe there is a meaningful functionaldifference between Action and MethodInvoker - they are essentially both defined as:
除了它们所在的命名空间之外,我认为Action 和 MethodInvoker 之间没有有意义的功能差异 - 它们基本上都定义为:
public delegate void NoParamMethod();
As an aside, Action has several overloads which allow parameters to be passed in - and it is generic so that they can be typesafe.
顺便说一句,Action 有几个重载,允许传入参数 - 它是通用的,因此它们可以是类型安全的。
回答by Jon Skeet
I prefer using lambdas and Actions/Funcs:
我更喜欢使用 lambdas 和 Actions/Funcs:
Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
回答by Orace
For each solution bellow I run a 131072 (128*1024) iterations (in one separated thread). The VS2010 performance assistant give this results:
对于下面的每个解决方案,我运行 131072 (128*1024) 次迭代(在一个单独的线程中)。VS2010 性能助手给出了这样的结果:
- read-only MethodInvoker: 5664.53 (+0%)
- New MethodInvoker: 5828.31 (+2.89%)
- function cast in MethodInvoker: 5857.07 (+3.40%)
- read-only Action: 6467.33 (+14.17%)
- New Action: 6829.07 (+20.56%)
- 只读 MethodInvoker:5664.53 (+0%)
- 新的 MethodInvoker:5828.31 (+2.89%)
- MethodInvoker 中的函数转换:5857.07 (+3.40%)
- 只读操作:6467.33 (+14.17%)
- 新动作:6829.07 (+20.56%)
Call to a new Actionat each iteration
在每次迭代时调用一个新的Action
private void SetVisibleByNewAction()
{
if (InvokeRequired)
{
Invoke(new Action(SetVisibleByNewAction));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, Actionat each iteration
在每次迭代时调用只读的内置构造函数和Action
// private readonly Action _actionSetVisibleByAction
// _actionSetVisibleByAction= SetVisibleByAction;
private void SetVisibleByAction()
{
if (InvokeRequired)
{
Invoke(_actionSetVisibleByAction);
}
else
{
Visible = true;
}
}
Call to a new MethodInvokerat each iteration.
在每次迭代时调用一个新的MethodInvoker。
private void SetVisibleByNewMethodInvoker()
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, MethodInvokerat each iteration
在每次迭代时调用只读的内置构造函数MethodInvoker
// private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker
// _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
private void SetVisibleByMethodInvoker()
{
if (InvokeRequired)
{
Invoke(_methodInvokerSetVisibleByMethodInvoker);
}
else
{
Visible = true;
}
}
Call to the function cast in MethodInvokerat each iteration
在每次迭代时调用MethodInvoker中的函数
private void SetVisibleByDelegate()
{
if (InvokeRequired)
{
Invoke((MethodInvoker) SetVisibleByDelegate);
}
else
{
Visible = true;
}
}
Example of call for the "New Action" solution :
调用“新操作”解决方案的示例:
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");
}
回答by Tomek
Don't forget to somehow check if control is available at the moment, to avoid errors at closing form.
不要忘记以某种方式检查当前是否可用,以避免关闭表单时出错。
if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));