跨线程从QML调用QObject函数

时间:2012-08-20 00:19:38

标签: c++ multithreading qt qml

我正在尝试确定如何从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中其他线程中的对象的方法是可以接受的。

4 个答案:

答案 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()

额外提示:您可以使用GammaRayThreadSanitizer查看当前跨线程的直接连接。

答案 3 :(得分:-1)

QML逻辑是事件驱动的,所有调用都是JavaScript函数的一部分。 JS函数可以是事件处理程序(例如UI事件处理程序),或者如果将它们包装在QScript对象中,则可以在C ++代码中的某处调用。您也可以在JavaScript WorkerTherad中调用它们。这就是为什么只有你能提供答案,someObj.someMethod()调用在哪里发生。