65

どちらがより正しいですか?またその理由は?

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したり、ラムダ式を書いたりするのに適切な時期はいつですか?

編集:ラムダとラムダの記述に大きな違いはないことは知っていますがActionMethodInvoker特定の目的のために作成されているようです。それは何か違うことをしていますか?

4

7 に答える 7

85

どちらも同じように正しいですが、ドキュメントには次のように記載されControl.Invokeています。

デリゲートは EventHandler のインスタンスにすることができます。その場合、sender パラメーターにはこのコントロールが含まれ、event パラメーターには EventArgs.Empty が含まれます。デリゲートは、MethodInvoker のインスタンス、または void パラメーター リストを受け取るその他のデリゲートにすることもできます。EventHandler または MethodInvoker デリゲートへの呼び出しは、別の種類のデリゲートへの呼び出しよりも高速です。

したがってMethodInvoker、より効率的な選択になります。

于 2009-07-22T19:55:14.197 に答える
29

以下のソリューションごとに、131072 (128*1024) 回の反復を (1 つのスレッドで) 実行します。VS2010 パフォーマンス アシスタントでは、次の結果が得られます。

  • 読み取り専用 MethodInvoker: 5664.53 (+0%)
  • 新しい MethodInvoker: 5828.31 (+2.89%)
  • MethodInvoker の関数キャスト: 5857.07 (+3.40%)
  • 読み取り専用アクション: 6467.33 (+14.17%)
  • 新しいアクション: 6829.07 (+20.56%)

反復ごとに新しいアクションを呼び出す

    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");
    }
于 2014-09-17T09:16:06.390 に答える
13

私はラムダとアクション/ファンクを使用することを好みます:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
于 2009-07-22T19:56:54.880 に答える
6

Action は System で定義されますが、MethodInvoker は System.Windows.Forms で定義されます。Action は他の場所に移植できるため、Action を使用する方がよい場合があります。MethodInvoker よりも Action をパラメーターとして受け入れる場所も多くあります。

ただし、ドキュメントには、Control.Invoke() 内の型 EventHandler または MethodInvoker のデリゲートへの呼び出しが他のどの型よりも高速になることが示されています。

それらがどのネームスペースにあるかは別として、私は Action と MethodInvoker の間に意味のある機能上の違いがあるとは思わない- 基本的に両方とも次のように定義されている:

public delegate void NoParamMethod();

余談ですが、 Action にはパラメーターを渡すことができるいくつかのオーバーロードがあり、タイプセーフになるようにジェネリックになっています。

于 2009-07-22T19:54:10.360 に答える
3

また、MSDNごとに:

MethodInvokerは、void パラメーター リストを使用してメソッドを呼び出すために使用される単純なデリゲートを提供します。このデリゲートは、コントロールの Invoke メソッドを呼び出す場合、または単純なデリゲートが必要だが自分で定義したくない場合に使用できます。

一方、アクションは最大 4 つのパラメータを取ることができます。

しかし、私はMethodInvokerActionの間に違いはないと思います。どちらもパラメーターをとらず、 voidを返すデリゲートをカプセル化するだけだからです。

それらの定義を見ると、これがわかります。

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

ところで、2行目を次のように書くこともできます。

Control.BeginInvoke(new MethodInvoker(DoSomething), null);
于 2009-07-22T19:54:01.203 に答える
2

DoSomething() メソッドを再利用するつもりでない限り、ほとんどの場合は好みの問題です。また、匿名関数はスコープ変数をヒープに配置するため、より高価な関数になる可能性があります。

于 2009-07-22T19:51:14.873 に答える
1

フォームを閉じる際のエラーを回避するために、現時点でコントロールが利用可能かどうかを何らかの方法で確認することを忘れないでください。

if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));
于 2017-12-20T11:55:55.003 に答える