時間のかかる処理の対策

[戻る]
NEO 2010/11/03(水) 13:58:51
MFC VC2005です。

左にツリービュー、右にフォームビューがある分割ウィンドウで、
ツリービューの選択アイテムを変更したときにフォームビューに表示する内容を変更する
アプリケーションがあります。

フォームビューで表示するものは、フォームビューのワーカースレッドで定期的に生成し
ています。
ツリービューの選択アイテムを変更したときには、フォームビューでそのワーカースレッ
ドをいったん終了させて、また新たにワーカースレッドを起動するようになっています。
新たにワーカースレッドを起動する前に、WaitForSingleObjectで古いワーカースレッド
の終了待ちをしていますが、その間はツリービュー(というかフレームウィンドウ全体)
が操作できなくなってしまいます。
これを解消して操作できるようにするにはどうすれば良いでしょうか?

なお、ワーカースレッドの終了は場合によっては時間がかかることがあります。

瀬戸っぷ [E-Mail] 2010/11/03(水) 23:52:27
ワーカースレッドに渡すデータに、「無効化」を通知するようなものを追加します。
# イベントオブジェクト辺りですかねぇ。

ワーカースレッドの終了待ちでは、無効化を通知した後は適当なタイミングでスレッドハ
ンドルの状態を監視するようにするとか
ワーカースレッドの終了直前にメインウィンドウなりにPostMessage()で通知して後始末
の契機をつけることにします。
ワーカースレッドは無効化が通知されたな、以降の画面描画関連を処理せずに明け渡し、
終了処理に移行させます。
フォームビュー側では新たに起動したワーカースレッドに画面描画関連を任せる。

というのはどうですかね?

まぁ、どんな作りになっているのか…で対処も変わるでしょうけど。

仲澤@失業者 2010/11/04(木) 12:40:42
親が子供の処理が終わるまで待っていたのではマルチスレッドの
意味がありませんねぇ。こういった処理は一般に
1.ワーカスレッドは起動したままで、状態変数(イベント等)を監視。
2.メイン側はワーカに状態変数の変更と、処理対象を指定するだけ。
3.ワーカは状態変数と処理対象が変更になったらそれなりの処理を続行するだけ。
4.ワーカは処理が完了したらメインにそれを通知する。んで、1.に戻る
5.メインはワーカの処理完了通知を感知したらそれを表示するだけ。
のようにコードします。

PATIO 2010/11/04(木) 15:19:31
スレッドを起こしたり、終わらせたりするのはオーバーヘッドが
大きいですから同じスレッドに対して渡す情報の内容を変更する
だけで済むのであれば、仲澤@失業者さんの方法が良いような気がします。

特にツリービュウ上の選択状態が変わる度にスレッドの処理内容の切替が
必要な場合、一々スレッドを起動/終了を繰り返していたらオーバーヘッドが
大きくてツリービュウの操作が重くなりそうです。
何処までツリービュウの操作とフォームビュウの連動を非同期にできるのか
と言う話もありますが、この辺は選択状態が変わってもすぐに変更されないか
適当な時間だけ処理開始を遅延するとかの対策も必要かもしれません。

ワーカースレッドとして裏で頑張っているとは言え、非常に重い処理が走れば
CPUの状態によってはメインスレッド側まで重くなる等の状況だって考えられます。
マルチスレッドは内部処理を進めつつ、オペレーターの操作にも対応する為の常套手段
ではありますが、万能と言うわけでは無いのでそこは考える必要があると思います。

NEO 2010/11/04(木) 20:22:19
[[解決]]
回答を下さった皆様、参考になりました。
ありがとうございました。

古いスレッドには追加発言できません。