简单例子理解 Qt 中 QObject: Cannot create children for a parent that is in a different thread. 问题

3 篇文章 0 订阅
2 篇文章 0 订阅

在做QT开发时,运行程序出现 如下警告:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(0xb95feffd70), parent's thread is QThread(0x1d3729aef20), current thread is QThread(0xb95feffd70) 

按字面意思可以理解为: 不能为属于不同线程的父对象创建子对象。由第二行提示可以看出来,当前线程与父对象属于的线程不是同一个线程,所以出现警告了。我们可以先看一个非常简单的例子,就很好理解了:

#ifndef THREADTEST2_H
#define THREADTEST2_H
#include <QThread>
#include <QDebug>

class Class1 : public QObject
{
public:
    Class1(QObject* parent) : QObject(parent){}
};

class ThreadTest2 : public QThread
{
public:
    ThreadTest2()
    {
        qDebug() << "ThreadTest2::ThreadTest2, thread = " << QThread::currentThread();
    }

    void run() override
    {
        qDebug() << "ThreadTest2::run, thread = " << QThread::currentThread();
        qDebug() << "ThreadTest2::run, ThreadTest2 thread = " << this->thread();
        m_class = new Class1(this);
    }

private:
    Class1* m_class = nullptr;
};

#endif // THREADTEST2_H

#include <QGuiApplication>
#include "qthreadtest.h"
#include "threadtest2.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    ThreadTest2 thread2;
    thread2.start();

    return app.exec();
}

运行结果:

ThreadTest2::ThreadTest2, thread =  QThread(0x2864244cbd0)
ThreadTest2::run, thread =  QThread(0x8d9d4ff7a8)
ThreadTest2::run, ThreadTest2 thread =  QThread(0x2864244cbd0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(0x8d9d4ff7a8), parent's thread is QThread(0x2864244cbd0), current thread is QThread(0x8d9d4ff7a8)

由运行结果看出 thread2(ThreadTest2)属于主线程(QThread(0x2864244cbd0)),我们尝试在 QThread(0x2864244cbd0)线程中为属于(QThread(0x2864244cbd0))的 thread2 对象创建子对象,所以出问题了。

那么我们可以如何避免出现这种问题呢,方法有很多种,下面介绍几种:

1. 创建对象时不指定父对象

既然问题出在为父对象创建子对象过程中,那么我们创建对象时不指定父对象不就好了,修改如下:

#ifndef THREADTEST2_H
#define THREADTEST2_H
#include <QThread>
#include <QDebug>

class Class1 : public QObject
{
public:
    Class1(QObject* parent = nullptr) : QObject(parent){}
};

class ThreadTest2 : public QThread
{
public:
    ThreadTest2()
    {
        qDebug() << "ThreadTest2::ThreadTest2, thread = " << QThread::currentThread();
    }

    void run() override
    {
        qDebug() << "ThreadTest2::run, thread = " << QThread::currentThread();
        qDebug() << "ThreadTest2::run, ThreadTest2 thread = " << this->thread();
        m_class = new Class1();
    }

private:
    Class1* m_class = nullptr;
};

#endif // THREADTEST2_H

显然这种方式不是很好,不指定父对象,创建的m_class对象的释放就要由自己管理了。我们可以看看其他方法。

2. 使用moveToThread设置对象绑定的线程

既然是因为在不同的线程创建子对象出问题了,那么我们将父对象属于的线程与执行线程设置为同一个线程不就好了吗。修改如下:

#include <QGuiApplication>
#include "qthreadtest.h"
#include "threadtest2.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    ThreadTest2 thread2;
    thread2.moveToThread(&thread2);
    thread2.start();

    return app.exec();
}

运行结果:

ThreadTest2::ThreadTest2, thread =  QThread(0x20f230c0d80)
ThreadTest2::run, thread =  QThread(0xb5db97fb58)
ThreadTest2::run, ThreadTest2 thread =  QThread(0xb5db97fb58)

可以看到thread2绑定的线程变为QThread(0xb5db97fb58),与run执行线程属于同一个线程了。

3. 将子对象的创建放到启动执行线程的线程中完成

既然是因为在不同的线程创建子对象出问题了,我们可以将子对象的创建放到父对象绑定的线程中创建就好了,就上面例子而言简单的方法就是将子对象的创建放到父对象的构造函数中:

#ifndef THREADTEST2_H
#define THREADTEST2_H
#include <QThread>
#include <QDebug>

class Class1 : public QObject
{
public:
    Class1(QObject* parent = nullptr) : QObject(parent){}
};

class ThreadTest2 : public QThread
{
public:
    ThreadTest2()
    {
        m_class = new Class1(this);
        qDebug() << "ThreadTest2::ThreadTest2, thread = " << QThread::currentThread();
    }

    void run() override
    {
        qDebug() << "ThreadTest2::run, thread = " << QThread::currentThread();
        qDebug() << "ThreadTest2::run, ThreadTest2 thread = " << this->thread();
    }

private:
    Class1* m_class = nullptr;
};

#endif // THREADTEST2_H

只要理解问题是怎么产生的,如何避免,之后再复杂的项目,也知道该如何解决啦。

  • 27
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
"QObject: Cannot create children for a parent that is in a different thread" 是一个错误消息,它表示在不同线程无法为父对象创建子对象。这个错误通常发生在Qt框架的应用程序,当你尝试在一个线程创建一个子对象,并将它的父对象设置为另一个线程的对象时。 这个错误的原因是Qt框架使用了线程安全的机制来确保对象的正确访问。每个对象都有一个与之相关联的线程,当你在一个线程创建一个对象时,这个对象的父对象必须与它在同一个线程。否则,就会出现上述错误。 为了解决这个问题,你可以考虑以下几种方法: 1. 确保在同一个线程创建父对象和子对象。这意味着你需要在同一个线程创建所有相关的对象。 2. 如果你确实需要在不同线程创建对象,可以使用信号和槽机制将父对象和子对象进行连接。这样可以确保子对象的创建是在正确的线程进行的。 3. 可能还有其他的解决方案,具体取决于你的应用程序的架构和需求。你可以查阅Qt框架的文档或者在Qt社区寻求帮助以获取更多的解决方案。 总之,"QObject: Cannot create children for a parent that is in a different thread" 错误通常是由在不同线程创建父对象和子对象引起的。通过确保在相同的线程创建相关对象,或者使用信号和槽机制进行连接,你可以解决这个错误。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [QObject: Cannot create children for a parent that is in a different thread错误](https://blog.csdn.net/lzjsqn/article/details/56287267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值