简体   繁体   English

MethodInvoker vs Action for Control.BeginInvoke

[英]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性能助手给出以下结果:

  • read-only MethodInvoker: 5664.53 (+0%) 只读MethodInvoker:5664.53(+ 0%)
  • New MethodInvoker: 5828.31 (+2.89%) 新方法召唤者:5828.31(+ 2.89%)
  • function cast in MethodInvoker: 5857.07 (+3.40%) 在MethodInvoker中强制转换的函数:5857.07(+ 3.40%)
  • read-only Action: 6467.33 (+14.17%) 只读操作:6467.33(+ 14.17%)
  • New Action: 6829.07 (+20.56%) 新动作:6829.07(+ 20.56%)

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 但是我认为MethodInvokerAction之间没有任何区别,因为它们都只是封装了一个不带参数且返回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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM