一回書いたのに消えた。死にたい。

Delphiの話です。
VCLはスレッドセーフではないとヘルプに記述されているが、最近までこれを誤解していた。
VCLとはVisual Component Libraryの略で、つまり主にヴィジュアルなメッセージを処理するコントロールのことを指すようだ。
これを、あらかじめ用意された便利なクラス群全てと勘違いしていた。つまりインスタンス=非スレッドセーフと笑
そうではないと分かったらこっちのもの(分かるの遅い)
TCriticalSectionの使い方もようやく分かった。

クリティカルセクションとは、複数のスレッド内である処理にゲートを設け、その区間内ではどれか一つのスレッドしか処理しないように規制できる機構だ。
つまり、同じデータやオブジェクトを扱う際に、同時に書き込みや操作をしないように出来る。

これを使う上で注意する点がある。
TThreadにはSynchronize関数があり、これはメインVCLスレッド内から同期して関数を読み出せるモノだが、その関数の処理が終わるまで制御は戻ってこない。
ということは、クリティカルセクションに入った状態でそれが実行され、さらに同期されたメインVCLスレッド内からクリティカルセクションに入ると・・
いわゆるデッドロックが起こるんですね。
これは参った。
スレッドに命令したい時はほとんどクリティカルセクションに入るので、これを外すようにするのは困難だ。
今までスレッド内で発生するイベントは全て同期していたが、これをやめ、イベントの処理はスレッドセーフであるということを前提で実装することにした。
そして、イベントを処理するユニットにグローバルなインスタンスのリスト(もちろんスレッドセーフ)を作っておき、タイマーを設けて、簡易なVCLスレッドによるメッセージ処理機構を作った。
そしてスレッドから呼ばれたイベント内で、そのリストにメソッドへのポインタを登録しておく。
処理が終了するのはこれだけでは検知できないが、これでデッドロックは免れられる。

ん~スレッドって奥が深いね!!
頭こんがらがりそうです。

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>