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
Why using QMetaObject::invokeMethod when executing method from thread
提问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 doSomething
it 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 QEvent
is 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::invokeMethod
if 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::invokeMethod
if 接收对象可能在另一个线程中的原因是,如果它访问或修改非线程安全数据,尝试直接在另一个线程中的对象上调用插槽可能会导致损坏或更糟。
回答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();
}