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

时间:2012-12-19 08:35:53

标签: c++ multithreading qt 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;
}

来自doSomething的问题必须通过QMetaObject::invokeMethod进行调用。我知道连接类型有一些东西。 是否有人可以解释引擎盖下的内容?

2 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:20)

我喜欢这个技巧:

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