1

MSDNのスレッドセーフ呼び出しチュートリアルを参照してください。次のステートメントを参照してください。

// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired) { 
    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke(d, new object[] { text });
} else {
    this.textBox1.Text = text;
}

もちろん、私はコードで何度も使用しており、使用する理由を少し理解しています。しかし、私はまだそれらの声明についていくつかの不明確な質問があるので、誰かが私がそれらを見つけるのを手伝ってください。

質問は次のとおりです。

  1. コードはif本文のステートメントでのみ正しく実行できますか?試してみましたが、コントロールが完全に初期化されていないと問題が発生するようです。もっと問題があるのか​​分かりませんか?
  2. 呼び出し元を介してメソッドを直接(他の本体)インスタンスを呼び出すことの利点はどれですか?リソース(CPU、RAM)などを節約できますか?

ありがとう!

4

2 に答える 2

2

もちろん、いつでもInvokerを使用して電話をかけることができますが、次のようになります。

  • これにより、通常、コードがより冗長になり、読みにくくなります。
  • 対処する追加のレイヤーがいくつかあるため(デリゲートの設定、ディスパッチャーの呼び出しなど)、効率が低下します。

常にGUIスレッドを使用していることが確実な場合は、上記のチェックを無視して直接呼び出すことができます。

于 2012-05-21T03:29:25.243 に答える
1
  1. ifステートメントの最初の部分だけを常に実行する場合Invokeは、UIスレッドを使用しているかどうかをすでに確認しているため、常に問題ありません。
    1. これを実行したくない理由はInvoke、既に正しいスレッドを使用している場合でも、メソッドを実行するために多くの作業を行う必要があるためです。これが何をしなければならないかです(Control.csのソースから抽出されました):
      • 親コントロールチェーンの上方トラバーサルを介してマーシャリングコントロールを見つけます
      • コントロールがActiveXコントロールであるかどうかを確認し、そうである場合は、管理されていないコードのアクセス許可を要求します
      • 潜在的なデッドロックを回避するために、呼び出しを非同期で呼び出す必要があるかどうかを確認します
      • デリゲートが最終的に呼び出されたときに同じセキュリティ権限が使用されるように、呼び出し元のスレッドの実行コンテキストのコピーを取ります
      • メソッド呼び出しをキューに入れ、メッセージを送信してメソッドを呼び出し、完了するまで待機します(同期している場合)。

すべての前提条件がすでに保証されているため、UIスレッドからの直接呼び出し中に、2番目のブランチの手順は必要ありません。したがって、コントロールを頻繁に更新しない限り、公平ではありますが、間違いなく高速になります。違いに気付く可能性はほとんどありません。

于 2012-05-28T05:10:36.027 に答える