24

ユーザーにプログレスバーを表示しながら、ワーカースレッドでいくつかの操作を実行したいと思います。クラスを作成しました

public class ProgressBar
{
   public void StartAsyncTask(Action action)
   {
      Task t = new Task(action);
      t.start();
   }
}

StartAsyncTask次の方法で任意のメソッドをに送信できることがわかりました。

  ProgressBar pb = new ProgressBar();
  pb.StartAsyncTask( () => DoSomething(15, "something"));

  public void DoSomething(int i, string s)
   {
      //do something
   }

まず第一に、ラムダ式とは何か、どのように() =>変換されるのか、そしてActionオブジェクトが不明な数のパラメーターを持つデリゲートをどのように渡すのかを理解できないようです。

ProgressBarでを使用しBackgroundWorkerたいのですが、この場合、アクションを呼び出す必要があります。だからこのようなもの:

void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    Action action = e.Argument as Action; //same action here passed through EventArgs
   //but already in a worker thread so no need for the Task object 

   //and now i need to somehow invoke the action object but i don't know what the parameters are. 

   action.Invoke( ? ); 
}

StartAsyncTask(Action action)最初の例で、メソッドのパラメーターを知らなくてもアクションを実行するにはどうすればよいですか?

この場合、アクションを呼び出すときにパラメーターを知る必要があるのはなぜですか?

ActionここでMSDNのドキュメントやその他のスレッドを読んだとしても、「」をどのように/なぜ/いつ使用するかについてのすべてが私にはかなり不明確です。これに関する情報は私を助けます。

4

2 に答える 2

55

あなたは物事を少し考えすぎていると思います。それでは、上から始めましょう。

  1. ラムダ式は、メソッドの実行を参照するための表記法です。例:

     x => x + 3
    

    最も基本的なレベルでは、これは1つの入力を受け取り、x次に、に等しい値を返す関数を表しますx + 3。だからあなたの状況では、あなたの表現:

    () => DoSomething(15, "Something")
    

    0個のパラメーターを取り、メソッドを呼び出すメソッドを表しますDoSomething(15, "Something")Funcコンパイラは、それをまたはActionデリゲートに変換する舞台裏にあります。だからそれは有効です:

    new Action(delegate()
    {
        DoSomething(15, "Something")
    }); 
    

    上記の私の単純な式のコンパイラの書き直しは次のようになります。

    new Func<int, int>(delegate(int x)
    {
        return x + 3;
    });
    
  2. 次に、後でアクションを呼び出したい場合、そのための構文はかなり簡単です。

    Action someMethod = new Action(() => { Console.WriteLine("hello world"); }));
    someMethod(); // Invokes the delegate
    

    したがって、特定のインスタンスがある場合は、構文Actionを使用してインスタンスを呼び出すだけで十分です。これは、0個のパラメーターを受け取り、何も返さないデリゲートであるためです。()Action

    関数も同様に簡単です。

    Func<int, int> previousGuy = x => x + 3;
    var result = previousGuy(3); // result is 6
    
  3. 最後に、呼び出すメソッドを渡したい場合で、その時点でパラメーターのコンテキストがない場合は、呼び出しをアクションでラップして、後で呼び出すことができます。例えば:

    var myAction = new Action(() =>
         {
              // Some Complex Logic
              DoSomething(15, "Something");
              // More Complex Logic, etc
         });
    
    InvokeLater(myAction);
    
    public void InvokeLater(Action action)
    {
          action();
    }
    

    すべてのデータはメソッドのクロージャーでキャプチャされるため、保存されます。したがって、プロパティActionを使用してイベントにを渡すことができれば、を呼び出すだけで済みます。e.Argument(e.Argument as Action)()

于 2012-11-06T22:42:20.503 に答える
2

DynamicInvoke()そのデリゲートで使用できません(params object[] args引数として使用します)

action.DynamicInvoke(arg1, arg2, arg3 );
于 2016-09-01T12:01:10.233 に答える