Зачем использовать QMetaObject:: invokeMethod при выполнении метода из потока

у меня есть следующий код:

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

вопрос почему из doSomething это должен быть вызов через QMetaObject::invokeMethod. Я знаю, что есть что-то с типом подключения. может ли кто-нибудь объяснить, что находится под капотом?

2 ответов


как вы не указали Qt::ConnectionType метод будет вызван как Qt::AutoConnection, что означает, что он будет вызываться синхронно (как обычный вызов функции), если сродство потока объекта к текущему потоку и асинхронно в противном случае. "Асинхронный" означает, что QEvent строится и помещается в очередь сообщений и будет обрабатываться, когда цикл событий достигнет его.

причина использовать QMetaObject::invokeMethod если объект получателя может быть в другом потоке попытка вызова слота непосредственно на объекте в другом потоке может привести к повреждению или хуже, если он обращается к или изменяет данные, не являющиеся потокобезопасными.


Мне нравится этот прием:

void A:doSomethingSlot()
{
     if (thread()!=QThread::currentThread()) {
         QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection);
         return;
     }
     // this is done always in same thread
     ...
     emit ready();
}