Question

Simple question: is it possible to detach a QObject from a QThread in order to move it to the main thread?

I use the following code:

QThread *thread = new QThread();

MyObject *object = new MyObject();

object->moveToThread(thread);

thread->start();

And somewhere after I want to move the MyObject instance to the main thread.

object->moveToThread(QApplication::instance()->thread());

I have the following error: QObject::moveToThread: Current thread (0x00000001) is not the object's thread (0x00000002). Cannot move to target thread (0x00000003).

Thanks

Was it helpful?

Solution

As the official doc says, moveToThread function can not "pull" an object from another thread, it "pushes" an object to another thread.

That's why if you want to change the thread affinity of your object, you should do it in the current object's thread.

I've added a simple example.

Here's Worker class:

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();
}

We create a Worker object, a QThread object and connect them with each other:

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();

That's what we got in the application output:

Worker::Worker(QObject*) QThread(0x1034680) true 
void Worker::doWork() QThread(0x1224970) false 
void Worker::doWork() Work is done 
void Worker::checkThread() QThread(0x1034680) true 

A Worker object is being created in the main application thread, then it does its work in a new thread. After job is done, it sends done() signal and moves itself back to the main thread. After a thread is finished we check that our Worker object is now really in the main thread again.

But really I don't understand why you may need this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top