10

我正在尝试确定如何从 QML 调用 QObject 插槽或 Q_INVOKABLE 方法来为存在于另一个线程中的 QObject 工作,以及这样做是否安全。

假设有一个 MainThread 和 ThreadA。QObjectA 位于 ThreadA 中。QML 引擎/gui/一切都存在于 MainThread 中。我使用 QObjectA 将 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 信号和插槽一样。

我想知道在跨线程从 QML 调用 C++ 方法时,Qt 的 qml 引擎是否会自动选择正确的类型,如果是这样,从 QML 调用存在于其他线程中的对象的方法是一种可接受的做法。

4

4 回答 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++ 中,因此需要一个中介对象。

于 2018-01-26T15:11:41.840 回答
0

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

但通常如果这会产生问题,那么我会做这样的事情。

连接(&threadA,信号(开始()),someObj,SLOT(someMethod());

但是要启动那个 ThreadA,我们还需要一个 CppObject 来链接 QML 和 CPP。

于 2012-08-21T10:31:39.787 回答
0

您可以使用 this->thread();QThread::currentThreadId();在插槽内获取插槽正在工作的线程。它将始终是线程,ObjectA 是在其中创建的(如果没有moveToThread())。

Qt-Engine 将Qt:ConnectionType通过确定调用和被调用线程来选择正确的。

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

于 2017-12-01T09:19:24.983 回答
-1

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

于 2012-08-21T07:33:39.873 回答