需要のないページ

プログラミングや趣味や。

マルチスレッドQtアプリケーション(1)

能書き

マルチスレッドをQtで再現する方法はいくつかあるが、

その中で、QThreadの継承を利用するものを紹介する。

 

コード:特にシンプルな例

まずはシンプルな例として、次のコードを書いてみた。

ヒープ領域を解放していなかったり、プログラムの終了条件がなかったり、

いろいろといい加減だが許してもらおう。

 

Q_DECL_OVERRIDEは、C++11以降ではoverrideに置換される。

このキーワードはもし無くてもエラーは生じない。

しかし、明記することで予期せぬ人的バグを回避できる。

 

QThreadのインスタンスをstart()すると、run()が内部的に呼び出される。

 

実行結果は次のとおりである。

Main: QThread(0x1881fe16160)
Sub: SubThread(0x1881fe17100)

実行結果は毎回異なるが、マルチスレッドが達成されていることは確認できる。

 

しかし、この方法には思わぬ落とし穴がある。

 

コード:うまくいかない例

直前の例に、一部を追加しただけのものだ。

マルチスレッドに親しんだ人から見れば、奇ッ怪なコードに見えることだろう。

しかし、直感的には実現できそうに写る。

コンストラクタ、メンバ関数、スロットとその呼び出しを追加した。  

 

実行結果は、次のとおりである。

Main: QThread(0x1b755747c70)
Constructor: QThread(0x1b755747c70)
Func: QThread(0x1b755747c70)
Sub: SubThread(0x1b755749ad0)
Slot: QThread(0x1b755747c70)

この実行結果の意味がわかるだろうか?

五つの出力のうち、下四つはSubThreadのメンバ関数によるものである。

しかし、スレッドのIDを見てみると、『Sub』以外はすべて同一である。

 

内的に呼び出される『run』関数以外、マルチスレッドの恩恵を受けられない。

 

原因と解決策

『原因』などと書いたが、これはQtの仕様通りの動作である。

 

『うまくいかない例』のようなインターフェースのまま、どう設計すればよいか?

継承ではなく、委譲を用いることでその要求を達成できる。

louis-needless.hatenablog.com

 

留意点

異なるスレッド間の関数呼び出しは本当は危険らしい。

面倒でもシグナル/スロットを用いると安全に実装できる。

/* コードブロック */