web-dev-qa-db-ja.com

BeginInvoke C#の使用方法

これを説明してください:

someformobj.BeginInvoke((Action)(() =>
{
    someformobj.listBox1.SelectedIndex = 0;
}));

begininvokeを正確に使用する方法を教えてください。 Actionタイプとは何ですか?空白のブラケット()があるのはなぜですか?そして、これは=>とはどういう意味ですか?

46

Action は、.NETフレームワークによって提供されるデリゲートのタイプです。 Actionは、パラメーターのないメソッドを指し、値を返しません。

() =>lambda expression 構文です。ラムダ式はタイプDelegateではありません。呼び出しにはDelegateが必要なので、Actionを使用してラムダ式をラップし、Invoke()に期待されるTypeを提供できます。

Invokeは、コントロールのウィンドウハンドルを作成したスレッドでActionを実行させます。 Exceptionsを回避するには、多くの場合、スレッドの変更が必要です。たとえば、最初にInvokeを呼び出すことなく、Invokeが必要なときにRtfRichTextBoxプロパティを設定しようとすると、Cross-thread operation not valid例外がスローされます。 Invokeを呼び出す前に、Control.InvokeRequiredを確認してください。

BeginInvokeは、Invokeの非同期バージョンです。非同期とは、ブロックしている同期呼び出しとは異なり、スレッドが呼び出し元をブロックしないことを意味します。

74
P.Brian.Mackey

あなたのコードはWindowsフォームに関連していると思います。
UIスレッドで何かを非同期に実行する必要がある場合は、BeginInvokeを呼び出します。ほとんどの場合、コントロールのプロパティを変更します。
大まかに言えば、これは定期的に実行されているいくつかのプロシージャにデリゲートを渡すことで達成されます。 (メッセージループ処理とそのようなもの)

BeginInvokeタイプに対してDelegateが呼び出された場合、デリゲートは非同期に呼び出されます。
Invoke同期バージョンの場合。)

WPFおよびWinFormsで完全に機能するより汎用的なコードが必要な場合は、タスク並列ライブラリを検討し、対応する contextTaskを実行することを検討してください。 (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()はタスクの終了までスレッドの呼び出しをブロックします。

タスクについて詳しく読む こちら

10
Pavel Voronin