1

アプリケーションは動作しているので (まだ) 問題はありませんが、後で問題が発生しないように、何が起こっているのかを理解したいと考えています。(私は主にデータベース/Web アプリケーションのプログラマーなので、通常、スレッドは私のものではありません!)

短いバージョン: UI は、複数のスレッドが更新しているときにフォーム データをロックする必要がありますか?

特定のコンテンツのファイルをスキャンし、結果をユーザーに表示する単純な Winforms アプリケーション (DataGridViews を使用) があります。私は最初、これをすべて UI スレッドで行いましたが、それは良い考えではないことを知り、項目の [ProcessorCount] コレクションに ThreadPool.QueueUserWorkItem を使用することにしました。これは正常に機能し、デリゲートと BeginInvoke 機能を使用して、見つかった結果を UI に送信します。(ただし、結果が多すぎて UI がまだ遅れている場合もありますが、それは別の問題です。)

ワーカー スレッドは完全に分離されており、独自の処理を行っています。複数のスレッドの概念と、共有データへの同時アクセスに注意する必要があることを理解しています。ただし、さまざまなスレッドが UI スレッドを呼び出して UI スレッドを更新するとどうなるかは、完全にはわかりません。UI だけがコントロール (およびフォーム レベルの変数) を更新しますが、呼び出しは他のスレッドから行われるため、これはどのように実行されるのでしょうか? たとえば、リストに項目を追加したり、カウンターをインクリメントしたりする場合、あるワーカー スレッドからの呼び出しが別のワーカー スレッドに割り込むことはありますか? 各 BeginInvoke は独自の呼び出しですが、データの変更は依然として問題になる可能性があるようです。

私が見つけた BeginInvoke の例のどれも、UI でロックする必要性について言及していません。これらの 2 つのトピックは関連していますが、私が探している正確な答えはまだ得られません。

lock(Control) の代わりに Control.Invoke() を使用する

Invoke() と BeginInvoke() の違いは何ですか

4

1 に答える 1

4

たとえば、リストに項目を追加したり、カウンターをインクリメントしたりする場合、あるワーカー スレッドからの呼び出しが別のワーカー スレッドに割り込むことはありますか? 各 BeginInvoke は独自の呼び出しですが、データの変更は依然として問題になる可能性があるようです。

いいえ、invoke 呼び出しは、別のそのような呼び出しによって中断することはできません。実際、UI スレッドの他の操作によって中断されることはありません。これが、UI スレッドを動作させると UI 自体が「ハング」する理由です (入力メッセージと描画メッセージは処理のためにキューに入れられますが、実行中の作業を中断することはできません)。

ただし、アイテムを に追加するList<T>(ということですか?) か、カウンターをインクリメントすることは、UI 操作ではありません。なぜUIスレッドでそれらを行うのですか?

UI スレッドでこのような操作を呼び出すと、副作用としてスレッドセーフなロックが得られるのは事実ですが、実際には無料ではありません。ワーカー スレッドで単純な操作を行うよりもはるかにコストがかかります。lock

このアプローチに切り替えることを検討する必要があります。これにより、「更新が多すぎる = ラグ」の問題も解決されます。

  • データ変数 (リスト、カウンターなど) は、ワーカー スレッドによって直接操作されます。適切なロック構造 ( lockInterlockedメソッド、並行コレクションなど) を使用して、スレッド セーフを提供します。
  • ワーカー スレッドがデータ変数を変更するたびに、グローバルmodifiedフラグも に設定しtrueます。
  • UI スレッドにマーシャリングされる (呼び出される)ものは何もありません。
  • 一方、UI スレッドは、たとえば 0.5 秒ごとに起動するようにタイマーを設定します。タイマーが起動するたびに、UI スレッドは の値をチェックしてmodifiedリセットしますfalse(これは でロックフリーで実行できますInterlocked.CompareExchange)。
  • UI スレッドは、データが変更されたことを検出すると、すべてのデータ変数をロックし、必要に応じて UI を再描画します。

この方法では、タイマー ティックごとに最大で 1 つの (高価な!) UI 更新のみが取得され、ワー​​カー スレッドからのデータの量に関係なく、UI が遅れることはありません。さらに、タイマー間隔を好きなだけ短くまたは長く選択できます。

于 2013-04-12T23:09:07.527 に答える