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

11

Решение

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

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

23

Другие решения

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

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

По вопросам рекламы [email protected]