跨线程从QML调用QObject函数

Calling a QObject function from QML across threads

本文关键字:QObject 函数 调用 QML 线程      更新时间:2023-10-16

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

假设有一个MainThread和ThreadA。QObjectA生活在ThreadA中。QML引擎/gui/所有东西都存在于MainThread中。我使用向QML引擎公开QObjectA

declarativeView->setContextProperty("someObj",ObjectA)

现在在QML文件中,我调用

someObj.someMethod();

其中someMethod是slot或是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为其他线程中的对象调用方法是可以接受的做法。

正如不久前显而易见的那样,QML似乎无法跨线程运行。

因此,需要实现一个位于主线程中的C++端中间对象,以便将调用分派到其他线程中的对象。

QML object -> object in a different thread // doesn't work!!!
QML object -> C++ mediator object -> object in a different thread // WORKS!!!

基本上,"超越"线程必须完全发生在C++中,因此需要一个中介对象。

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

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

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

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

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

Qt引擎将通过确定调用和被调用线程来选择正确的Qt:ConnectionType

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

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