これを説明してください:
someformobj.BeginInvoke((Action)(() =>
{
someformobj.listBox1.SelectedIndex = 0;
}));
begininvoke
を正確に使用する方法を教えてください。 Action
タイプとは何ですか?空白のブラケット()
があるのはなぜですか?そして、これは=>
とはどういう意味ですか?
Action
は、.NETフレームワークによって提供されるデリゲートのタイプです。 Action
は、パラメーターのないメソッドを指し、値を返しません。
() =>
は lambda expression 構文です。ラムダ式はタイプDelegate
ではありません。呼び出しにはDelegate
が必要なので、Action
を使用してラムダ式をラップし、Invoke()
に期待されるType
を提供できます。
Invoke
は、コントロールのウィンドウハンドルを作成したスレッドでAction
を実行させます。 Exceptions
を回避するには、多くの場合、スレッドの変更が必要です。たとえば、最初にInvokeを呼び出すことなく、Invokeが必要なときにRtf
のRichTextBox
プロパティを設定しようとすると、Cross-thread operation not valid
例外がスローされます。 Invokeを呼び出す前に、Control.InvokeRequired
を確認してください。
BeginInvoke
は、Invoke
の非同期バージョンです。非同期とは、ブロックしている同期呼び出しとは異なり、スレッドが呼び出し元をブロックしないことを意味します。
あなたのコードはWindowsフォームに関連していると思います。
UIスレッドで何かを非同期に実行する必要がある場合は、BeginInvoke
を呼び出します。ほとんどの場合、コントロールのプロパティを変更します。
大まかに言えば、これは定期的に実行されているいくつかのプロシージャにデリゲートを渡すことで達成されます。 (メッセージループ処理とそのようなもの)
BeginInvoke
タイプに対してDelegate
が呼び出された場合、デリゲートは非同期に呼び出されます。
(Invoke
同期バージョンの場合。)
WPFおよびWinFormsで完全に機能するより汎用的なコードが必要な場合は、タスク並列ライブラリを検討し、対応する context でTask
を実行することを検討してください。 (TaskScheduler.FromCurrentSynchronizationContext()
)
そして、他の人がすでに言ったことに少し付け加えると、ラムダは匿名メソッドまたは expressions として扱うことができます。
それが、ラムダでvar
を使用できない理由です。コンパイラにはヒントが必要です。
UPDATE:
これには.Net v4.0以降が必要です
// This line must be called in UI thread to get correct scheduler
var scheduler = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();
// this can be called anywhere
var task = new System.Threading.Tasks.Task( () => someformobj.listBox1.SelectedIndex = 0);
// also can be called anywhere. Task will be scheduled for execution.
// And *IF I'm not mistaken* can be (or even will be executed synchronously)
// if this call is made from GUI thread. (to be checked)
task.Start(scheduler);
他のスレッドからタスクを開始し、その完了を待つ必要がある場合、task.Wait()
はタスクの終了までスレッドの呼び出しをブロックします。
タスクについて詳しく読む こちら 。