Control.BeginInvoke 的 MethodInvoker 与 Action

发布于 2024-07-29 01:07:53 字数 497 浏览 2 评论 0原文

哪个更正确,为什么?

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 与 Action 的正确时机,甚至是编写 lambda 表达式?

编辑:我知道编写 lambda 与 Action 之间并没有太大区别,但 MethodInvoker 似乎是为特定用途。 它有什么不同吗?

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?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

后来的我们 2024-08-05 01:07:53

两者都同样正确,但 Control.Invoke 的文档 指出:

委托可以是一个实例
EventHandler,在这种情况下是发送者
参数将包含此控件,
并且事件参数将包含
EventArgs.Empty。 代表还可以
是 MethodInvoker 的实例,或者
任何其他代表作废
参数列表。 致电
EventHandler 或 MethodInvoker 委托
比调用另一个更快
委托类型。

所以 MethodInvoker 将是一个更有效的选择。

Both are equally correct, but the documentation for Control.Invoke states that:

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.

So MethodInvoker would be a more efficient choice.

断肠人 2024-08-05 01:07:53

对于下面的每个解决方案,我运行 131072 (128*1024) 次迭代(在一个单独的线程中)。
VS2010 性能助手给出以下结果:

  • 只读 MethodInvoker:5664.53 (+0%)
  • 新 MethodInvoker: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;
        }
    }

“新操作”解决方案的调用示例:

    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");
    }

For each solution bellow I run a 131072 (128*1024) iterations (in one separated thread).
The VS2010 performance assistant give this results:

  • 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%)

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.

    private void SetVisibleByNewMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
        }
        else
        {
            Visible = true;
        }
    }

Call to a read-only, build in constructor, MethodInvoker at each iteration

    // 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

    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");
    }
简单 2024-08-05 01:07:53

我更喜欢使用 lambda 和 Actions/Funcs:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));

I prefer using lambdas and Actions/Funcs:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
你如我软肋 2024-08-05 01:07:53

Action 是在 System 中定义的,而 MethodInvoker 是在 System.Windows.Forms 中定义的 - 您最好使用 Action,因为它可以移植到其他地方。 您还会发现比 MethodInvoker 接受 Action 作为参数的地方更多。

但是,文档确实表明在 Control.Invoke() 中调用 EventHandler 或 MethodInvoker 类型的委托将比任何其他类型更快。

除了它们所在的命名空间之外,我不认为 Action 和 MethodInvoker 之间存在有意义的功能差异 - 它们本质上都定义为:

public delegate void NoParamMethod();

顺便说一句,Action 有几个重载,允许参数被传入 - 并且它是通用的,因此它们可以是类型安全的。

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.

However, the documentation does indicate that calls to delegates of type EventHandler or MethodInvoker in Control.Invoke() will be faster than any other type.

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:

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.

执笔绘流年 2024-08-05 01:07:53

另外,根据 MSDN:

MethodInvoker 提供了一个简单的委托,用于调用带有 void 参数列表的方法。 当调用控件的 Invoke 方法时,或者当您需要一个简单的委托但不想自己定义一个委托时,可以使用此委托。

另一方面,操作最多可以使用 4 个参数。

但我认为 MethodInvokerAction 之间没有任何区别,因为它们都只是封装了一个不接受参数并返回 void 的委托。 。

如果你看看他们的定义,你就会明白这一点

public delegate void MethodInvoker();
public delegate void Action();

顺便说一句,你也可以将第二行写为。

Control.BeginInvoke(new MethodInvoker(DoSomething), null);

Also per MSDN:

MethodInvoker provides 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.

an Action on the other hand can take up to 4 parameters.

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

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);
赴月观长安 2024-08-05 01:07:53

在大多数情况下,这只是一个偏好问题,除非您打算重用 DoSomething() 方法。 此外,匿名函数会将作用域变量放置在堆上,可能会使其成为更昂贵的函数。

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.

海夕 2024-08-05 01:07:53

不要忘记以某种方式检查当前控件是否可用,以避免关闭表单时出现错误。

if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));

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"));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文