c++ - 修复 QObject : Cannot create children for a parent that is in a different thread

标签 c++ c++11 qt5

我在 Qt Creator 的应用程序输出中注意到此消息:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QUdpSocket(0x557d126bb830), parent's thread is QThread(0x557d11d1d680), current thread is QThread(0x557d126c64d0)

我使用:

  • GCC 13.2.1 作为编译器。
  • Qt 5.15.11。
  • Qt Creator 11.0.3。

我的项目有点大,所以我提供 minimal reproducible example 。它包含用于发送UDP数据包的UDPClient类和用于准备UDP数据包的MyProcessing类。

main.cpp:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QMainWindow w;
    w.show();

    UDPClient c(&w, QHostAddress("192.168.1.255"), 5001);
    MyProcessing p(NULL, "Hi!");

    QTimer timer;
    timer.setInterval(1000);
    timer.setTimerType(Qt::TimerType::PreciseTimer);

    QObject::connect(&timer, SIGNAL(timeout()), &p, SLOT(onTimeout()));
    QObject::connect(&p, SIGNAL(sigNewDataReady(QByteArray)),
                     &c, SLOT(onNewUDPDataReceived(QByteArray)),
                     Qt::DirectConnection);

    p.start();
    timer.start();

    return a.exec();
}

udpclient.h:

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <QObject>
#include <QThread>
#include <QUdpSocket>

class UDPClient : public QObject
{
    Q_OBJECT
public:
    explicit UDPClient(QObject *parent = nullptr,
                       QHostAddress aAddr = QHostAddress("192.168.0.20"),
                       quint16 aPortNum = 0);
public slots:
    void onNewUDPDataReceived(QByteArray data);

private:
    QUdpSocket  *udpSocket;
    quint16      portNum;
    QHostAddress addr;
};

#endif // UDPCLIENT_H

udpclient.cpp:

#include "udpclient.h"

UDPClient::UDPClient(QObject *parent, QHostAddress aAddr, quint16 aPortNum)
    : QObject{parent}
{
    portNum = aPortNum;
    addr    = aAddr;
    udpSocket = new QUdpSocket();
}

void UDPClient::onNewUDPDataReceived(QByteArray data)
{
    udpSocket->writeDatagram(data, addr, portNum);
} 

myprocessing.h:

#ifndef MYPROCESSING_H
#define MYPROCESSING_H

#include <QObject>
#include <QThread>

class MyProcessing : public QObject {
    Q_OBJECT
public:
    MyProcessing(QObject *parent = nullptr, QByteArray text = "text");

    void start() { mThread->start(); }

signals:
    void sigNewDataReady(QByteArray);

public slots:
    void onTimeout() {emit sigNewDataReady(QByteArray(mText)); }

private:
    QByteArray mText;
    QThread *mThread;
};

#endif // MYPROCESSING_H

myprocessing.cpp:

#include "myprocessing.h"

MyProcessing::MyProcessing(QObject *parent, QByteArray text)
    : QObject{parent}
{
    mText = text;
    mThread = new QThread;
    this->moveToThread(mThread);
}

Other questions在类似的应用程序输出上建议不要从 QThread 类继承,并建议使用与我在这里所做的类似的方式。

最佳答案

按照@G.M建议使用QThread::currentThreadId,我发现错误是由main.cpp中的Qt::DirectConnection引起的。 Qt::DirectConnection 导致 SLOT(onNewUDPDataReceived(QByteArray))p 的线程中运行。 看看这个link以获得更多解释。

只需删除 Qt::DirectConnection 即可解决问题。

关于c++ - 修复 QObject : Cannot create children for a parent that is in a different thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77494158/

相关文章:

c++ - 如何修改参数包的每个元素,并从中创建一个元组?

c++ - 如何从 std::thread 更改 GUI?

android - 在 android 的 QTextEdit 中选择

c++ - 不确定如何处理析构函数(类中的大型顶点数组用作同一类的其他实例的数据源)

c++ - 使用Qt拖放: Knowing target application on hover - is it possible?

c++ - 在模板派生类中继承具有类型别名的构造函数

c++ - 使用运行时参数桥接模板

c++ - 在不分配内存的情况下使用 placement new 是否安全?

c++ - 无法在同一文件中定义 2 个不同类的构造函数

ios - 为 iOS 构建 Qt