[英]MethodInvoker vs Action for Control.BeginInvoke
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
vs Action
或什至编写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. 编辑:我知道编写lambda与Action
之间并没有太大的区别,但是MethodInvoker
似乎是为特定目的而设计的。 Is it doing anything different? 它有什么不同吗?
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. 委托可以是EventHandler的实例,在这种情况下,发送者参数将包含此控件,而事件参数将包含EventArgs.Empty。 The delegate can also be an instance of MethodInvoker, or any other delegate that takes a void parameter list. 该委托也可以是MethodInvoker的实例,也可以是采用无效参数列表的任何其他委托。 A call to an EventHandler or MethodInvoker delegate will be faster than a call to another type of delegate. 调用EventHandler或MethodInvoker委托要比调用另一种委托更快。
So MethodInvoker
would be a more efficient choice. 因此, MethodInvoker
将是一个更有效的选择。
For each solution bellow I run a 131072 (128*1024) iterations (in one separated thread). 对于下面的每个解决方案,我都会运行131072(128 * 1024)个迭代(在一个单独的线程中)。 The VS2010 performance assistant give this results: VS2010性能助手给出以下结果:
Call to a new Action at each iteration 每次迭代都调用一个新的动作
private void SetVisibleByNewAction()
{
if (InvokeRequired)
{
Invoke(new Action(SetVisibleByNewAction));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, Action at each iteration 调用一个只读的,构建在构造函数中, 行动在每次迭代
// private readonly Action _actionSetVisibleByAction
// _actionSetVisibleByAction= SetVisibleByAction;
private void SetVisibleByAction()
{
if (InvokeRequired)
{
Invoke(_actionSetVisibleByAction);
}
else
{
Visible = true;
}
}
Call to a new MethodInvoker at each iteration. 每次迭代都调用一个新的MethodInvoker 。
private void SetVisibleByNewMethodInvoker()
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, MethodInvoker at 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 MethodInvoker at 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");
}
我更喜欢使用lambda和Actions / Funcs:
Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
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. Action是在System中定义的,而MethodInvoker是在System.Windows.Forms中定义的-使用Action可能会更好,因为它可以移植到其他地方。 You will also find more places that accept Action as a parameter than MethodInvoker. 与MethodInvoker相比,您还会发现更多接受Action作为参数的位置。
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 functional difference 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具有多个重载,它们允许传入参数-并且它是通用的,因此它们可以是类型安全的。
Also per MSDN: 同样根据MSDN:
MethodInvoker provides a simple delegate that is used to invoke a method with a void parameter list. MethodInvoker提供了一个简单的委托,该委托用于调用带有无效参数列表的方法。 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. 调用控件的Invoke方法时,或者当您需要一个简单的委托但不想自己定义一个委托时,可以使用此委托。
an Action on the other hand can take up to 4 parameters. 另一方面,一个动作最多可以包含4个参数。
But I don't think there is any difference between MethodInvoker and Action as 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);
It is a matter of preference in most cases, unless you intend to reuse the DoSomething() method. 在大多数情况下,这是一个优先事项,除非您打算重用DoSomething()方法。 Also the anonymous functions will place your scoped variables on the heap, might make it a more expensive function. 另外,匿名函数会将您的作用域变量放在堆上,可能会使它变得更昂贵。
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"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.