Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why using QMetaObject::invokeMethod when executing method from thread

I have following code:

class A : public QObject
{
    Q_OBJECT
public:
    A() : QObject()
    {
         moveToThread(&t);
         t.start();
    }
    ~A()
    {
         t.quit();
         t.wait();
    }

    void doSomething()
    { 
         QMetaObject::invokeMethod(this,"doSomethingSlot");
    }
public slots:
    void doSomethingSlot()
    {
         //do something
         emit ready();
    }
signals:
    void ready();
private:
    QThread t;
}

The question why from doSomething it must be call via QMetaObject::invokeMethod. I know that there is something with connection type. Could some one explain what is under the hood?

like image 521
krzych Avatar asked Dec 19 '12 08:12

krzych


2 Answers

As you haven't specified a Qt::ConnectionType, the method will be invoked as Qt::AutoConnection, which means that it will be invoked synchronously (like a normal function call) if the object's thread affinity is to the current thread, and asynchronously otherwise. "Asynchronously" means that a QEvent is constructed and pushed onto the message queue, and will be processed when the event loop reaches it.

The reason to use QMetaObject::invokeMethod if the recipient object might be in another thread is that attempting to call a slot directly on an object in another thread can lead to corruption or worse if it accesses or modifies non-thread-safe data.

like image 144
ecatmur Avatar answered Nov 13 '22 11:11

ecatmur


I like this trick:

void A:doSomethingSlot()
{
     if (thread()!=QThread::currentThread()) {
         QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection);
         return;
     }
     // this is done always in same thread
     ...
     emit ready();
}
like image 28
Marek R Avatar answered Nov 13 '22 10:11

Marek R