3

フォーム/コントロール/要素 (通常はメイン スレッド) をインスタンス化したスレッドで実行されているコードが、その要素を同時に変更/アクセスしないと仮定しましょう。

  1. TextBox の Text プロパティを取得します。

  2. ListView を列挙します。

  3. Form の Closing イベントをサブスクライブします。(そのフォームをインスタンス化したスレッドからフックが呼び出されることを知っている)

3つすべてを試しましたが、プログラムはそれについて文句を言わないようです。私は常に、UI 関連 (読み取りまたは書き込み) にリモートで触れたい場合は、呼び出しを呼び出す必要があると考えていました。

要素を変更するときに IsInvokeRequired/Invoke パターンを使用する必要がある理由は非常に明確に理解していますが、プロパティ/イベントにアクセスすると問題が発生する理由はわかりません。

4

3 に答える 3

5

確かに可能ですが、予期しない動作につながる可能性があります。また、他のスレッド関連のバグも考慮する必要があります。たとえば、競合状態/デッドロックなどです。 Managed Threading Best Practicesを参照してください。

安全のために、私は常に UI スレッドで UI にアクセスすることに固執します。

于 2012-12-20T16:01:38.310 に答える
3

また、UI スレッドからの読み取り中にコントロールが変更されないようにするために、何をしていますか? UI スレッドにマーシャリングする全体的な理由は、そのケースについて心配する必要がないようにするためです。特にリストボックスの列挙は、最も長い時間がかかるため、最も簡単に中断できます (これにより、競合状態の最大のウィンドウが作成されます)。これら 3 つすべてについて、UI スレッドにマーシャリングする必要があります。

于 2012-12-20T16:02:15.687 に答える
2

これは安全ではありません。別のスレッドからコントロールを読み取っている間に、UI スレッドがコントロールの状態を変更する可能性があります (おそらくそうするでしょう)。あなたの読み取りは、中途半端な状態でコントロールをキャッチする可能性があります。今はうまくいっているように見えるかもしれませんが、遅かれ早かれ失敗するでしょう...おそらく予測不可能で壮観です。

いいえ、おそらく Invoke パターンを使用する必要はありません。率直に言って、そのパターンは通常最悪の選択肢です。通常は、ワーカー スレッドに手間のかかる作業を行わせてから、新しいデータまたは進行状況の情報をキュー経由で UI スレッドに送信し、UI スレッドがタイマー経由でこれを取得できるようにすることをお勧めします。これにはいくつかの利点があります。

  • 高価な操作を排除しInvokeますBeginInvoke
  • UI スレッドは、ワーカー スレッドに命令させる代わりに、いつ、どのくらいの頻度で新しいデータを更新する必要があるかを決定します。
  • Invokeワーカー スレッドが戻るのを待つ必要がないため、ワーカー スレッドのスループットが向上します。
  • の場合のように、UI メッセージ キューがオーバーランするリスクはありませんBeginInvoke
  • UI とワーカー スレッドの相互作用を分離します。

ListViewを列挙し、ワーカー スレッドが安全にアクセスできる別のデータ構造を構築する必要があります。に多くの項目が含まれている場合はListView、コントロールと連携して別のコレクションを維持することを検討してください。そうすれば、データに対処するというペナルティをより長い期間にわたって分散させることができます。結局、コピー操作によって UI スレッドがフリーズすることは望ましくありません。AConcurrentBagなどは、ワーカー スレッドが読み取り中に UI スレッドによって安全に変更できるため、適切な選択です。

于 2012-12-20T20:52:53.787 に答える