Подтвердить что ты не робот

Зачем использовать 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. Я знаю, что есть что-то типа подключения. Может кто-нибудь объяснить, что находится под капотом?

4b9b3361

Ответ 1

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

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

Ответ 2

Мне нравится этот трюк:

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