QObject::setParent: 无法设置父级,新父级在不同的线程中

QObject::setParent: Cannot set parent, new parent is in a different thread

问候

我有一个追随者class。

class MyClass : public QObject
{
    Q_OBJECT

public:
    Q_INVOKABLE QVariant status();

public:
    MyClass(ClassX * classX);

public slots:
    void slotA();
    void slotB();

signals:
    void signalA();
    void signalB();

private:
    void init();
    void doSomething();

private:
    ClassX * classX;
    ClassA classA;
    ClassB classB;
};

MyClass的构造函数中,我将classX设置为this.classX,在init()中,我connect一些classX信号到 MyClass 插槽,反之亦然,在 someFunction() 中,我使用 classAclassB.

在主线程中的 controller class 中,我创建了 MyClass 对象,并在不同的线程中创建了 运行 它。

MyClass * myClass = new MyClass(classX);
connect(&myClassThread, SIGNAL(started()), myClass, SLOT(init()));
myClass->moveToThread(&myClassThread);
myClassThread.start();

我在 qDebugger 中看到以下警告。

QObject::setParent: Cannot set parent, new parent is in a different thread

谁能告诉我为什么会收到该警告?

在此先致谢

PS 1: classX在主线程中创建。

PS 2:记住,一切正常,我没有任何问题,我只是想知道这个警告的原因以及如何解决它。

PS 3 : 我也在主线程中使用以下命令来暴露 javascript.

中的对象
webFrame->addToJavaScriptWindowObject("myClassObject", myClass);

编辑 1:QThread myClassThread 是 class 成员。

编辑 2:我认为信息的缺乏让你们感到困惑,对此我深表歉意。

MyClass的构造函数是这样的:

MyClass::MyClass(ClassX * classX)
{
     this.classX = classX;
}

这在很多方面都是错误的:

QThread myClassThread;
MyClass * myClass = new MyClass(classX);
connect(&myClassThread, SIGNAL(started()), myClass, SLOT(init()));
myClass->moveToThread(&myClassThread);
myClassThread.start();
  1. 您正在堆栈上而不是堆上创建线程 object!这意味着 myClassThread object 将在该代码块结束时被销毁。
  2. myClass 有一个 parent。 Object 被移动到线程不能有任何 parent。只有 object 中的全部三个可以移动到线程

让我们说清楚。 您的代码未按预期运行。 这就是框架告诉您的情况。

QObject::setParent: Cannot set parent, new parent is in a different thread

这意味着某个对象(怀疑myClass)的所有槽和信号都不会像预期的那样在同一个线程中执行。这里的问题围绕 myClassclassX objects

的父对象

可能性一:myClass->moveToThread(&myClassThread);正在失败

原因: myClass 已经设置了父类。这是被禁止的。

表示init()会被线程对象myClassThread的线程触发。在线程和事件方面,这与您所做的几乎相同

MyClass * myClass = new MyClass(classX);
QMetaObject::invokeMethod(myClass, "init", Qt::QueuedConnection);

可能性 II:init() 违反了线程亲和性

原因:`classX``或者一个神秘的相关对象已经设置了父对象或者不能移动到另一个线程。想想小部件。

moveToThread 成功,你在一个线程中有 MyClass,在另一个线程中有 classX。您在构建 myClass 时提供了 classXmyClass 现在正在另一个线程中操作一个对象,如果没有进一步的代码,我们不能假设线程安全或正确的子父关联。仔细阅读 MyClass::MyClass` 和 MyClass::init。

发生了哪一个?

尝试在调试器、控制器代码中打断并查看线程 ID。然后在 init 方法中的调试器中打断。

  • 如果是同一个线程,情况一
  • 否则就是情况二