公式ドキュメントが言うように、moveToThread
関数は別のスレッドからオブジェクトを「プル」することはできず、オブジェクトを別のスレッドに「プッシュ」します。
そのため、オブジェクトのスレッド アフィニティを変更する場合は、現在のオブジェクトのスレッドで行う必要があります。
簡単な例を追加しました。
Worker
クラスは次のとおりです。
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
signals:
void done();
public slots:
void doWork();
void checkThread();
private:
bool isMainThread();
};
Worker::Worker(QObject *parent) :
QObject(parent)
{
qDebug() << __PRETTY_FUNCTION__
<< QThread::currentThread()
<< isMainThread();
}
void Worker::doWork()
{
qDebug() << __PRETTY_FUNCTION__
<< QThread::currentThread()
<< isMainThread();
qDebug() << __PRETTY_FUNCTION__ << "Work is done";
moveToThread(qApp->thread());
emit done();
}
void Worker::checkThread()
{
qDebug() << __PRETTY_FUNCTION__
<< QThread::currentThread()
<< isMainThread();
}
bool Worker::isMainThread()
{
return QThread::currentThread() == qApp->thread();
}
Worker
オブジェクト、オブジェクトを作成し、QThread
それらを相互に接続します。
QThread *thread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(doWork()));
QObject::connect(worker, SIGNAL(done()), thread, SLOT(quit()));
QObject::connect(thread, SIGNAL(finished()), worker, SLOT(checkThread()));
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
それが、アプリケーションの出力で得られたものです。
Worker::Worker(QObject*) QThread(0x1034680) true
void Worker::doWork() QThread(0x1224970) false
void Worker::doWork() Work is done
void Worker::checkThread() QThread(0x1034680) true
Worker
オブジェクトはメイン アプリケーション スレッドで作成され、新しいスレッドでその作業を行います。ジョブが完了すると、done()
シグナルを送信し、メイン スレッドに戻ります。Worker
スレッドが終了したら、オブジェクトが本当にメイン スレッドに戻っていることを確認します。
しかし、なぜこれが必要なのか、本当にわかりません。