時々突然落ちますけど…その2
さて関数drawPixmap()ですが、画像情報を持つQPixmapのインスタンスを渡してそれを再描画する関数です。
ここでdrawPixmap()を呼んでいるのは、QMainWindowクラスのメソッドpaintEvent()で、メインウィンドウの描画が必要になると呼ばれます。このメインウィンドウはメインスレッドで実行されます。
QPixmapのインスタンスにJPEGの画像情報を設定してこれを渡すのですが、このJPEG情報を設定するのが実はグラフィック描画用のスレッド(メインスレッドとは別のスレッド)なのです。
再描画処理(paintEvent())はJPEGファイルを受け取った時だけではなく、ウィンドウの再描画が必要になった時に非同期に呼ばれるのでした…つまり、運悪く画像描画中に他のスレッドが画像のデータを書き換えたりしたら何が起こるかわからないんですね。
ということで、1つのスレッドが描画している間は、他のスレッドが使っているデータを書き換えたりしないように制御してやる必要があります。これがいわゆる排他制御ですね。シングルスレッドで実装していた昔なら問題なかったのですがスレッドに分けた時点で気づいてませんでした。
QPixmapのインスタンス内部の情報を書き換えたり、参照したりする時は他のスレッドが書き換えたり、参照できないようにします。このためにQReadWriteLockを利用します。
QReadWriteLock lock;
[JPEGデータ設定(書き込み)時] : グラフィック描画用スレッド
lock.lockForWrite();
bool imageLoadResult = pixmap->loadFromData((const uchar *)buffer,(uint)receivedDataSize);
lock.unlock();
[JPEGデータb描画(参照)時] : メインスレッド
lock.lockForRead();
QPainter painter(this);
painter.drawPixmap(0, 0, *pixmap);
lock.unlock();
ブリュンヒルデ零式改(zeroshikikai.cpp)の場合GlobalAlloc()とGlobalUnlock()で結果的に制御されているため問題なしということでしょうか。
もう少し動作確認をして、アルファテスト的なリリースパッケージを作ろうかなと思います。
#まず「パブリックモードとは」から説明するためのマニュアルが必要でしょうね…
« 時々突然落ちますけど…その1 | トップページ | やっぱり落ちますけど… »
コメント