从QML跨线程调用QObject函数

11

我想确定在调用另一个线程中的QObject槽或Q_INVOKABLE方法时,从QML调用是否能够正常工作,以及是否安全。

假设有一个主线程和ThreadA。QObjectA位于ThreadA中。QML引擎/ GUI / 所有内容都位于主线程中。我使用某种方式将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调用其他线程中的对象的方法是否是可以接受的做法。


您可以使用 qDebug() << "Main thread: " << QThread::currentThreadId(); 来确定函数的运行位置。正如其他评论所述,不应假设某些未记录的行为将在将来的版本中保持一致。 - mozzbozz
你参考了Qt 4.7文档。你正在使用Qt 4.7吗? - king_nak
4个回答

2
正如一段时间前显而易见的那样,QML 似乎无法跨线程访问。
因此,需要实现一个 C++ 中间对象,该对象位于主线程中,以调度其他线程中的对象的调用。
QML object -> object in a different thread // doesn't work!!!
QML object -> C++ mediator object -> object in a different thread // WORKS!!!

基本上,“超越”线程必须完全在C++中进行,因此需要一个中介对象。

0

我猜someMethod将在ThreadA中执行,因为该对象存在于该线程中。

但通常如果出现问题,我会这样做。

connect(&threadA, SIGNAL(started()), someObj, SLOT(someMethod());

但要启动ThreadA,我们需要一个额外的CppObject来链接QML和CPP。


你说得对,为对象设置信号和槽会起作用。但是如果有大量的槽,则可能会不太方便,因此我想了解从QML调用方法的具体细节。 - Prismatic
是的,其实我也有同样的感觉。连接过多的信号和槽会导致轻微的混乱。我会检查上述情况,并报告是否正常工作。 - RajaRaviVarma

0

在槽函数中,您可以使用 this->thread(); 或者 QThread::currentThreadId(); 来获取槽函数所在的线程。如果没有使用 moveToThread(),那么它将始终是 ObjectA 创建的线程。

Qt 引擎会根据调用和被调用的线程来选择正确的 Qt:ConnectionType

额外提示:您可以使用 GammaRay 或者 ThreadSanitizer 来查看跨线程的当前直接连接。


-1

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


我觉得你误解了我的意思。我正在将一个QObject传递给QML引擎。默认情况下,如果QObject有任何标记为Q_INVOKABLE的方法或任何槽,您可以直接从qml文件调用这些方法。 QML引擎使用invokeMethod()来执行该方法。我希望找出的是它是否使用Queued或Direct连接类型来执行此操作。被调用的不是JS函数,而是C ++函数。 - Prismatic
2
我相信基于框架未记录的实现细节做出任何架构决策都不是一个好主意。请自行适当地进行连接类型选择。 - Pavel Osipov
并不存在所谓的“WorkerTherad”,甚至连“WorkerThread”都不是,而是有一个名叫“WorkerScript”的东西,其访问和使用方面受到严格限制。 - dtech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接