BeginInvoke()
とInvoke()
areの違いは何ですか?
主にそれぞれ何に使うのか。
編集: スレッド オブジェクトの作成とその上での呼び出しBeginInvoke()
と、デリゲートでの呼び出しの違いは何ですか? それとも同じものですか?
BeginInvoke()
とInvoke()
areの違いは何ですか?
主にそれぞれ何に使うのか。
編集: スレッド オブジェクトの作成とその上での呼び出しBeginInvoke()
と、デリゲートでの呼び出しの違いは何ですか? それとも同じものですか?
Delegate.Invoke
/BeginInvoke
またはControl.Invoke
/のことBeginInvoke
ですか?
Delegate.Invoke
: 同じスレッドで同期的に実行されます。Delegate.BeginInvoke
threadpool
:スレッド上で非同期に実行します。Control.Invoke
: UI スレッドで実行されますが、呼び出しスレッドは続行する前に完了を待ちます。Control.BeginInvoke
: UI スレッドで実行され、呼び出しスレッドは完了を待ちません。ティムの答えは、いつ使用したいかについて言及していますBeginInvoke
-それは主に に向けられていましたがDelegate.BeginInvoke
、私は疑っています。
Windows フォーム アプリの場合、通常はを使用することをお勧めしますBeginInvoke
。そうすれば、たとえばデッドロックを心配する必要はありませんが、次に UI を見るまでに UI が更新されていない可能性があることを理解する必要があります。特に、UI スレッドが表示目的で使用しようとしているデータは変更しないでください。たとえば、Person
withプロパティがあり、次のようにしたFirstName
とLastName
します。
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
その後、UI に "Keyser Spacey" が表示される可能性があります。(「Kevin Soze」を表示できる外的可能性がありますが、メモリ モデルの奇妙さによってのみです。)
ただし、この種の問題がない限り、問題を解決するのControl.BeginInvoke
は簡単で、バックグラウンド スレッドが正当な理由もなく待機する必要がなくなります。Control.BeginInvoke
Windows フォーム チームは、「ファイア アンド フォーゲット」方式で使用できることを保証していることに注意してください。つまり、 を呼び出す必要はありませんEndInvoke
。これは一般的な非同期呼び出しには当てはまりません。通常、すべての BeginXXX には対応する EndXXX 呼び出しが必要であり、通常はコールバック内にあります。
Jon Skeet の回答に基づいて、デリゲートを呼び出し、その実行が完了するのを待ってから現在のスレッドを続行したい場合があります。そのような場合、 Invoke 呼び出しが必要です。
マルチスレッド アプリケーションでは、特にデリゲートが I/O を実行する (デリゲートとスレッドがブロックされる可能性がある) 場合は、スレッドがデリゲートで実行を終了するのを待機したくない場合があります。
そのような場合、BeginInvoke が役立ちます。それを呼び出すことで、デリゲートに開始するように伝えますが、スレッドはデリゲートと並行して他のことを自由に実行できます。
BeginInvoke を使用するとコードが複雑になりますが、パフォーマンスの向上が複雑さに見合う場合があります。
Control.Invoke()
との違いControl.BeginInvoke()
は、
BeginInvoke()
GUIスレッドで非同期アクションをスケジュールします。非同期アクションがスケジュールされると、コードは続行されます。しばらくして (正確なタイミングはわかりません)、非同期アクションが実行されます。Invoke()
(GUI スレッドで) 非同期アクションを実行し、アクションが完了するまで待機します。論理的な結論として、渡すデリゲートInvoke()
は out-parameters または return-value を持つことができますが、渡すデリゲートはBeginInvoke()
できません (結果を取得するには EndInvoke を使用する必要があります)。
それらの違いの影響を確認するための短い実用的な例を示すだけです
new Thread(foo).Start();
private void foo()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
myTextBox.Text = "bing";
Thread.Sleep(TimeSpan.FromSeconds(3));
});
MessageBox.Show("done");
}
BeginInvokeを使用すると、テキストの更新と同時に MessageBox がポップされます。Invokeを使用すると、MessageBox は 3 秒間のスリープ後にポップします。したがって、非同期 ( BeginInvoke ) 呼び出しと同期 ( Invoke ) 呼び出しの効果を示しています。
Delegate.BeginInvoke() は、デリゲートの呼び出しを非同期的にキューに入れ、すぐに制御を返します。Delegate.BeginInvoke() を使用する場合は、コールバック メソッドで Delegate.EndInvoke() を呼び出して結果を取得する必要があります。
Delegate.Invoke() は、同じスレッドでデリゲートを同期的に呼び出します。