18

我有以下代码:

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。我知道有一些与连接类型有关的东西。有人可以解释引擎盖下的内容吗?

4

2 回答 2

33

由于您没有指定 a Qt::ConnectionType,因此该方法将被调用为Qt::AutoConnection,这意味着如果对象的线程亲和性与当前线程相关,它将被同步调用(如普通函数调用),否则异步调用。“异步”意味着aQEvent被构造并推送到消息队列中,并在事件循环到达它时被处理。

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

于 2012-12-19T08:56:13.497 回答
29

我喜欢这个技巧:

void A:doSomethingSlot()
{
     if (thread()!=QThread::currentThread()) {
         QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection);
         return;
     }
     // this is done always in same thread
     ...
     emit ready();
}
于 2012-12-19T09:27:27.470 回答