QThread の Qt ドキュメントには、QThread からクラスを作成し、run メソッドを実装するように記載されています。
以下は 4.7 Qthread ドキュメントから抜粋したものです...
独自のスレッドを作成するには、QThread をサブクラス化し、run() を再実装します。例:
class MyThread : public QThread
{
public:
void run();
};
void MyThread::run()
{
QTcpSocket socket;
// connect QTcpSocket's signals somewhere meaningful
...
socket.connectToHost(hostName, portNumber);
exec();
}
そのため、私が作成したすべてのスレッドで、まさにそれを実行し、ほとんどの場合、問題なく動作します (どのオブジェクトにも moveToThread(this) を実装していませんが、問題なく動作します)。
先週、行き詰まってしまいました(オブジェクトを作成した場所を回避することでなんとか乗り越えました)。次のブログ投稿ここでは基本的に、QThread をサブクラス化するのは実際には正しい方法ではない (そしてドキュメントが間違っている) と述べています。
これは Qt 開発者からの意見なので、一目見て興味を持ちましたが、よく考えてみると、彼の意見に同意します。OO の原則に従うと、クラスをさらに強化するためにクラスをサブクラス化することだけが望ましいのです。クラスのメソッドを直接使用するだけでは不十分です。そのためにインスタンス化します。
たとえば、カスタム QObject クラスをスレッドに移動したいとします... それを実行する「正しい」方法は何でしょうか? そのブログ投稿では、どこかに例があると「言っています」... しかし、誰かが私にそれをさらに説明してくれると非常にありがたいです!
アップデート:
この質問は非常に注目を集めているため、QThread を実装する「適切な」方法を記載した 4.8 ドキュメントのコピーと貼り付けを以下に示します。
class Worker : public QObject
{
Q_OBJECT
QThread workerThread;
public slots:
void doWork(const QString ¶meter) {
// ...
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
不必要で、例ではまったく使用されていない余分なメンバーが含まれていることを指摘することは価値があると私はまだ信じていますWorker::workerThread
。その部分を削除すれば、Qt でスレッドを実行する方法の適切な例になります。
ベストアンサー1
私が追加できる唯一のことは、QObject
が単一のスレッドと親和性を持っていることをさらに述べることです。これは通常、 を作成するスレッドですQObject
。したがって、アプリのメイン スレッドで を作成し、それを別のスレッドで使用したい場合は、 を使用して親和性を変更するQObject
必要があります。moveToThread()
QThread
これにより、サブクラス化してメソッド内でオブジェクトを作成する必要がなくなりrun()
、内容が適切にカプセル化されます。
そのブログ記事には、例非常に短いですが、基本的な考え方を示しています。 を作成しQObject
、シグナルを接続し、 を作成し、を にQThread
移動して、スレッドを開始します。シグナル/スロット メカニズムにより、スレッド境界が適切かつ安全に越えられるようになります。QObjects
QThread
そのメカニズムの外部でオブジェクトのメソッドを呼び出す必要がある場合は、同期を導入する必要があるかもしれません。
Qtには他にも良い点があるのは知っていますスレッド機能おそらく知っておく価値があるスレッドもありますが、私はまだそうしていません :)