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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13948337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:50:58  来源:igfitidea点击:

Why using QMetaObject::invokeMethod when executing method from thread

c++multithreadingqtqthread

提问by krzych

I have following code:

我有以下代码:

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;
}

The question why from doSomethingit must be call via QMetaObject::invokeMethod. I know that there is something with connection type. Could some one explain what is under the hood?

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

回答by ecatmur

As you haven't specified a Qt::ConnectionType, the method will be invoked as Qt::AutoConnection, which means that it will be invoked synchronously (like a normal function call) if the object's thread affinity is to the current thread, and asynchronously otherwise. "Asynchronously" means that a QEventis constructed and pushed onto the message queue, and will be processed when the event loop reaches it.

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

The reason to use QMetaObject::invokeMethodif the recipient object might be in another thread is that attempting to call a slot directly on an object in another thread can lead to corruption or worse if it accesses or modifies non-thread-safe data.

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

回答by Marek R

I like this trick:

我喜欢这个技巧:

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