かきくけこうもりのよろず投資日記(旧サイト)
 
このサイトは移転しました。サイト右側のリンクから、新しいブログに移動できます。
 


2006年6月15日を表示

ぬるぽの回避でデッドロックみたいなのに遭遇する

マケスピのRSSからとってきたデータをフォームに表示させようとしたのですが、このデータ取得部分はフォームのスレッドとは別のスレッドでやっています。そのため、フォームの画面の更新にはInvokeメソッドを使っています。
ここでフォームの閉じるボタンを押すと、データ取得用のスレッドが終了する前にフォームオブジェクトが破棄されてしまうので、破棄されたフォームに対してデータ取得スレッドがInvokeメソッドを呼び出してしまい、ぬるぽ(ガッみたいなエラーが出てしまいます。
そこで、これを回避するために、フォームオブジェクトを破棄する際に呼ばれる関数をオーバーロードして、その前にスレッドを終了させてみようと思いました。
ところがヘルプを見ても、こういうスレッドの使い方をしたときに、どのタイミングでスレッドを停止すればいいのかということがわかりませんでした(もう少し詳しく読めばどっかに書いてありそうだけど)。
まずFinalizeをオーバーロードしてみたのですが、こうすると全く改善が見られず、結局Invokeメソッドのところでぬるぽ。そこでDisposeをオーバーロードしてみたのですが、ここでわけのわからない挙動に嵌ってしまいました。
データ取得用スレッドを終了させる方法として、スレッドの挙動を管理するBool型の変数を用意。データ取得用スレッドを起動したときにはこのフラグをTrueにしておき、これがFalseになるまでループを回してデータを取得。で、フォームが破棄されるときにこのフラグを外部からFalseにして、さらにjoinで待機することによって、無限ループを開放してスレッドを自然に終了させようとしました。
この方法は、フォームの破棄以外のタイミングでやると正常に動作します。joinの待機時間は60秒に設定していますが、実際にはあっという間にスレッドが終了してくれます。joinの待機時間をオーバーした場合にはAbortで無理やり停止させるようにしていますが、こんなことは起こりません。
しかし、Dispose関数内部からこの方法を呼び出すと、何故かjoinの待機時間が終わるまで待たされます。何で?
しかもjoinの待機時間中には、データ取得用スレッドそのものが全く動かない状態になってしまいます。さらに、joinの待機時間を過ぎてAbortが呼び出されると、joinによって勝手に止められていたスレッドがようやく動き出して、スレッド停止フラグを検出してスレッドが終了する、という有様。どうも、Disposeから呼び出したjoinが待機しているスレッドは、データ取得用スレッドじゃない何か別のモノみたい。
で、解決策なのですが、join関数の手前にapplication.doevents()を追加したら、何故か解決してしまいました。何で?理由が全くわからないです。
多分Dispose関数は複数回呼ばれるとかヘルプに書いてあったので、それが原因?
                 |l| | |l| |
                 _,,..,,,,_
                ./ ゚ 3  `ヽーっ
                l ゚ ll ⊃ ⌒_つ
                )`'ー---‐'''''"(_
                ⌒)   (⌒   ビターン
                  ⌒



6月15日(木) | トラックバック(0) | コメント(0) | 日記 | 管理


(1/1ページ)