修复 QObject:无法为位于不同线程中的父线程创建子项

Fix QObject: Cannot create children for a parent that is in a different thread

提问人:Veljko 提问时间:11/16/2023 最后编辑:Veljko 更新时间:11/21/2023 访问量:130

问:

我在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的。

我的项目有点大,所以我提供了最小的可重复示例。它包含用于发送 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);
}

关于类似应用程序输出的其他问题建议不要继承 QThread 类,并建议使用与我在这里所做的类似的方式。

C C++11 QT5

评论

0赞 eyllanesc 11/16/2023
更改为new QUdpSocket(this)
0赞 Veljko 11/16/2023
我试过了。。。相同的结果
0赞 Osyotr 11/17/2023
onUDPServerThreadStarted在主线程中运行,这是你的意图吗?
2赞 G.M. 11/21/2023
编辑您的问题以提供最小的可重现示例。另请注意,如果您想知道您的方法在哪个线程上被调用,您可以检查/比较 QThread::currentThreadId 的输出。onUDPServerThreadStarted
1赞 Veljko 11/21/2023
@G.M.感谢您的使用建议,我找到了发生错误的原因,我解决了它。我有责任编辑这个问题,这样我就可以在最小的可重现示例中显示错误以及解决它的原因。QThread::currentThreadId

答:

2赞 Veljko 11/21/2023 #1

按照@G.M的建议,我发现错误是由main.cpp引起的。 导致在线程中运行。 查看此链接以获取更多解释。QThread::currentThreadIdQt::DirectConnectionQt::DirectConnectionSLOT(onNewUDPDataReceived(QByteArray))p

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