進行状況バーをユーザーに表示しながら、ワーカースレッドでいくつかの操作を実行したいと思います。クラスを作成しました
_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のドキュメントや他のスレッドをここで読んだとしても、私にはかなり明確ではありません。これに関する情報は私に役立ちます。
あなたは物事を少し考え過ぎていると思います。それでは、上から始めましょう:
ラムダ式は、メソッドの実行を参照する表記法です。例:
_ 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;
});
_
次に、アクションを後で呼び出したい場合、そうするための構文はかなり簡単です:
_Action someMethod = new Action(() => { Console.WriteLine("hello world"); }));
someMethod(); // Invokes the delegate
_
したがって、Action
インスタンスは、Action
が0パラメーターを受け取り、何も返さないデリゲートであるため、_()
_構文を使用して呼び出すだけで十分です。
関数も同様に簡単です。
_Func<int, int> previousGuy = x => x + 3;
var result = previousGuy(3); // result is 6
_
最後に、呼び出すメソッドを渡して、その時点でパラメーターのコンテキストがない場合、呼び出しをアクションにラップして、後で呼び出すことができます。例えば:
_var myAction = new Action(() =>
{
// Some Complex Logic
DoSomething(15, "Something");
// More Complex Logic, etc
});
InvokeLater(myAction);
public void InvokeLater(Action action)
{
action();
}
_
すべてのデータはメソッドのクロージャーでキャプチャされるため、保存されます。したがって、e.Argument
_プロパティを使用してAction
をイベントに渡すことができた場合は、_(e.Argument as Action)()
_を呼び出すだけで十分です。
そのデリゲートでDynamicInvoke()
を使用することはできません(params object[] args
引数として)
action.DynamicInvoke(arg1, arg2, arg3 );