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

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

本文关键字:于不同 线程 setParent 设置 QObject      更新时间:2023-10-16

问候语

我有以下课程。

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() 中,我将classX一些信号connectMyClass插槽,反之亦然,someFunction()我使用 classAclassB

在主线程的controller类中,我创建了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 是类成员。

编辑2:我相信缺乏信息,让你们感到困惑,对此我很抱歉。

MyClass的构造函数是这样的:

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

让我们明确一点。您的代码未按预期工作。这就是框架告诉你的。

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

这意味着某个对象(疑似myClass)的所有插槽和信号将不会在与预期相同的线程中执行。这里的问题围绕着myClassclassX对象的父对象

可能性 I : myClass->moveToThread(&myClassThread); 失败

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

这意味着init()将由线程对象myClassThread的线程触发。线程和事件方面,这几乎与您所做的相同

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

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

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

moveToThread成功,您必须在一个线程中MyClass,在另一个线程中classX。您在构造myClass时提供了classXmyClass现在正在另一个线程中操作一个对象,如果没有进一步的代码,我们就无法假设线程安全或正确的子父亲和性。仔细查看MyClass ::MyClass' 和 MyClass::init。

哪一个正在发生?

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

  • 如果是同一线程,则情况 I
  • 否则就是案例二

在很多方面都是错误的:

QThread myClassThread;
MyClass * myClass = new MyClass(classX);
connect(&myClassThread, SIGNAL(started()), myClass, SLOT(init()));
myClass->moveToThread(&myClassThread);
myClassThread.start();
  1. 您是在堆栈上而不是在堆上创建线程对象!这意味着当此代码块结束时myClassThread对象将被销毁。
  2. myClass有一个父母。移动到线程的对象不能有任何父对象。只能将整整三个对象移动到线程