ここで説明されているように、GUI コントロールへのクロススレッド アクセスの一般的なセットアップを見てきました 。
私が見つけたすべての Web ヒットは、同様のことを説明しています。
しかし、なぜ InvokeRequired を確認する必要があるのでしょうか。Invoke を直接呼び出すことはできませんか?
答えはノーだと思いますので、私の本当の質問は「なぜ」ですか?
ここで説明されているように、GUI コントロールへのクロススレッド アクセスの一般的なセットアップを見てきました 。
私が見つけたすべての Web ヒットは、同様のことを説明しています。
しかし、なぜ InvokeRequired を確認する必要があるのでしょうか。Invoke を直接呼び出すことはできませんか?
答えはノーだと思いますので、私の本当の質問は「なぜ」ですか?
非 UI スレッドから UI に触れることはできません。コントロールにはスレッド アフィニティがあるため、非常に悪いことが起こる可能性があります。そのため、非 UI スレッドから (少なくとも) Invoke
orを呼び出す必要がありBeginInvoke
ます。
ただし、UI スレッドの場合は、多くの時間を呼び出したくありません。Invoke
問題は、既に UI スレッドを使用している場合でも、フォームのポンプにメッセージを送信して処理するという不必要なオーバーヘッドがまだあることです。
実際には、ほとんどのスレッド化コードでは、非UI スレッドで特定のメソッドが呼び出されることが予想されるため、そのような場合、追加のオーバーヘッドはありません。Invoke
InvokeRequired
基本的に、正しいスレッドで実行しているかどうかがわかります。正しいスレッドにいない場合は、タスクを正しいスレッドにマーシャリングする必要があります。そうでない場合はそうしません。したがって、チェックが必要です。
ウィンドウ ハンドルが作成される前に呼び出そうとすると (たとえば、フォーム コンストラクターを呼び出すとき) InvalidOperationException
、. そのため、一般的にInvokeRequired
チェックが必要です。
詳細については、 MSDNを参照してください。
問題は、GUI コントロールには、GUI コントロールのインスタンス化に使用されたのと同じスレッドで実行されるコードのみが GUI コントロールにアクセスできるという要件があることです。この要件の背後にある理由は、Windows の設計方法に関係しています。これを変えるのは非常に難しいと言っておきましょう。
InvokeRequired は、インスタンス化スレッドの ID に対して、現在実行中のスレッドの ID をチェックします。それらが同じである場合、コードはコントロールと自由に対話できます。そうでない場合、コードは現在のスレッドからインスタンス化スレッドまでデータをマーシャリングする必要があります。これは時間とコストのかかるプロセスであり、可能な限り回避する必要があります。常に呼び出すとコードは機能し、パフォーマンスの低下に気付かない可能性がありますが、マルチコア システムが使用されるようになると、このシナリオはますます一般的になります。後で元に戻す必要があるコードの「結び目」を作成しないことをお勧めします。
Invoke は、コストがかかる直接ではなく、Delegate を介してコードを呼び出します。
必要な場合にのみ Invoke を呼び出すと、費用対効果が高くなります。したがって、InvokeRequired は、呼び出しが同じスレッドから行われたのか、それとも別のスレッドから行われたのかを調べるために使用されます。
私が考えることができる 1 つの理由は、パフォーマンスです。ほとんどの場合、呼び出し元のスレッドが作成元のスレッドと同じである場合、不必要なオーバーヘッドが発生します。