为什么在从线程执行方法时使用QMetaObject :: invokeMethod

krz*_*ych 12 c++ qt multithreading qthread

我有以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

问题为什么doSomething必须通过它来调用QMetaObject::invokeMethod.我知道连接类型有一些东西.有人可以解释引擎盖下的内容吗?

eca*_*mur 23

因为你没有指定a Qt::ConnectionType,所以该方法将被调用为Qt::AutoConnection,这意味着如果对象的线程亲和性是当前线程,它将被同步调用(如普通函数调用),否则将异步调用."异步"表示QEvent构造并推送到消息队列,并在事件循环到达时处理.

QMetaObject::invokeMethod如果收件人对象可能在另一个线程中,则使用的原因是,尝试直接在另一个线程中的对象上调用插槽可能会导致损坏,或者如果它访问或修改非线程安全数据则会更糟.


Mar*_*k R 20

我喜欢这个伎俩:

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

  • 不要这样做,使用编译时检查:`QMetaObject::invokeMethod(this, [this]{ doSomethingSlot(); }, Qt::QueuedConnection);` (2认同)