- ある画像をマルチスレッド(分割統治法など)で事前にレンダリングしておき、キャッシュする。
- OnPaintでそのキャッシュを使う。
なんて事をしようと思いまして、スレッドプールを使って処理をさせ、レンダリングが終わったらワーカースレッド側でManualResetEventのSet()を呼び出し、メインスレッド側ではWaitOneで各ワーカースレッドが終わるのを待つ・・・・というような処理を書きました。
で、たまに描画結果が期待したものにならない事がありまして調べてみると、
どうやらWaitOneで待っている間にOnPaintが呼ばれてしまう事があるようなのです。
(当然その段階ではキャッシュは作り終わっていないので、描画がおかしくなるというわけです。)
このような挙動は過去にMFCなどでネイティブアプリを作っている時には起こり得なかったため、特定に時間がかかりました。
WinFormsはそういう作りになっているそうです。
参考:
http://stackoverflow.com/questions/4540244/how-is-this-possible-onpaint-processed-while-in-waitone
ただ、WaitOneだけならともかく、他にもメインスレッドを待つ処理だったり、.NETのフレームワークの一部の機能を使ったとき(例えばクリップボードに格納されているデータを確認するとき)のような意図しない時にもOnPaintが呼ばれるのが厄介です。
(ツールバーの「貼り付け」ボタンの状態を更新しようとしたらOnPaintが呼ばれる、なんて事もありえます。)
こうした場合、
- マルチスレッドで画像をレンダリングするのを止める(^^;
- キャッシュを使わないようにする
- OnPaintの中でキャッシュを作るようにする
- フラグでなんとか回避する
などなど、注意してプログラムする必要がありそうです。
何か良いアイディアをご存知の方がいらっしゃいましたら、ご連絡くださいm(_ _)m
(先の参考サイトだとMutexなら起こらないとか書かれていますが、今回のケースだと使えないような?)