我正在尝试确定如何从QML中为生活在另一个线程中的QObject调用QObject槽或Q_INVOKABLE方法,以及它是否安全。
假设有一个MainThread和ThreadA。 QObjectA位于ThreadA中。 QML引擎/ gui / Everys都存在于MainThread中。我使用
将QObjectA暴露给QML引擎declarativeView->setContextProperty("someObj",ObjectA)
现在在QML文件中,我打电话给
someObj.someMethod();
其中someMethod是一个插槽或者是Q_INVOKABLE。我想知道哪个线程实际执行该函数。如果它是MainThread,那将是一件坏事,并且在线程之间调用这样的方法会很危险。如果它是由ThreadA执行的,那么一切都会好的。
基于此文档:http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html,我假设使用QMetaObject :: invokeMethod()来调用QObject函数。该文档(http://doc.qt.nokia.com/4.7-snapshot/qmetaobject.html#invokeMethod)表明存在不同的连接类型,就像Qt信号和插槽一样。
我想知道Qt的qml引擎是否在跨线程从QML调用C ++方法时自动选择正确的类型,如果是这样的话,调用QML中其他线程中的对象的方法是可以接受的。
答案 0 :(得分:1)
就像前面became apparent一样,QML似乎无法跨越线程。
因此,需要实现一个C ++端中间对象,该对象位于主线程中,以便调用其他线程中的对象。
For example:
var privateFunction = function() {
this.flag = false;
}
this.$onInit= function() {
this.flag = true;
privateFunction();
}
基本上,“超越”线程必须完全在C ++中发生,因此需要一个中介对象。
答案 1 :(得分:0)
我想someMethod将在ThreadA中执行,因为该对象存在于该线程中。
但通常如果这会产生问题,那么我会做这样的事情。
connect(& threadA,SIGNAL(started()),someObj,SLOT(someMethod());
但是为了启动ThreadA,我们还需要一个CppObject来链接QML和CPP。
答案 2 :(得分:0)
您可以在插槽中使用this->thread();
或QThread::currentThreadId();
来获取插槽工作的线程。它始终是线程,ObjectA是在(如果没有{{1 }})。
Qt-Engine将通过确定呼叫和被叫线程来选择正确的moveToThread()
。
额外提示:您可以使用GammaRay或ThreadSanitizer查看当前跨线程的直接连接。
答案 3 :(得分:-1)
QML逻辑是事件驱动的,所有调用都是JavaScript函数的一部分。 JS函数可以是事件处理程序(例如UI事件处理程序),或者如果将它们包装在QScript对象中,则可以在C ++代码中的某处调用。您也可以在JavaScript WorkerTherad中调用它们。这就是为什么只有你能提供答案,someObj.someMethod()调用在哪里发生。