【问题标题】:QObject::setParent: Cannot set parent, new parent is in a different threadQObject::setParent:无法设置父级,新父级在不同的线程中
【发布时间】:2016-03-08 13:28:29
【问题描述】:

问候

我有以下课程。

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 类中,我创建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;
}

【问题讨论】:

  • 这很容易成为第 n 个问题。 MyClass * myClass = new MyClass(classX); 应该是 MyClass * myClass = new MyClass(0);。句号。
  • @UmNyobe 即使没有参数,我仍然会收到警告
  • @UmNyobe 这不是重复的问题,如您所见,我通过信号槽调用了 myClass 的方法!即使我不调用任何方法,甚至在创建后不使用对象,我仍然会收到警告
  • 我没有提到信号和插槽。如果上面的代码 sn-p 不能与 new Myclass(0) 一起使用,那么它与您的真实代码不同(因为上面的代码仅用于问题陈述)。

标签: c++ multithreading qt qthread qtwebkit


【解决方案1】:

让我们说清楚。 您的代码没有按照您的预期工作。这是框架告诉您的。

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

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

可能性一: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 方法中的调试器中打一个break。

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

【讨论】:

  • 非常感谢您的回答,我明白了
【解决方案2】:

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

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

【讨论】:

  • 关于 1 :我刚刚添加了编辑 1,myClassThread 实际上是类成员。关于 2:myClass 的父级是 QObject。我不认为这是造成它的原因
  • 您正在将 myClass 移动到另一个线程,但 classX 保留在主线程中。因此发出警告。如果要将 myClass 移动到另一个线程,请不要使用 classX 作为 myClass 的父级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
相关资源
最近更新 更多