QObject:无法为不同线程中的父级创建子级。(Parent是QTcpSocket)

时间:2016-07-24 12:39:19

标签: c++ multithreading qt

我是qt的初学者。我在qt文档中采用了QThread Class推荐的方式。 文档中使用的方法如下。

   class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const QString &parameter) {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::operate, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

所以我分别有Class SocketThreadCtrler和Class SocketWorker。 具体代码如下。

socketthreadctrler.h如下。

#ifndef SOCKETTHREADCTRLER_H
#define SOCKETTHREADCTRLER_H

#include <QObject>
#include <QThread>
#include "socketworker.h"

class SocketThreadCtrler : public QObject
{
    Q_OBJECT
private:
    QThread workThread;
public:
    explicit SocketThreadCtrler(QObject *parent = 0);
    ~SocketThreadCtrler();
private:
    void connSigAngSlots();
public slots:
    void login(QString acnt, QString passwd);
    void EmitSigCheckLogin(bool loginStatus);

signals:
    void SIG_CONECTSERVER();
    void SIG_WRITEMSG(QByteArray&);
    void SIG_CHECKLOGIN(bool);

private:
    SocketWorker* worker;
//    MainUI* mainUI;
};

#endif // SOCKETTHREADCTRLER_H

socketThreadCtrler.cpp

#include "header/backend/communication/socketthreadctrler.h"
#include "header/backend/communication/smessage1.h"

SocketThreadCtrler::SocketThreadCtrler(QObject *parent) : QObject(parent)//, worker(NULL)
{
//    SocketWorker* worker = new SocketWorker();
    worker=new SocketWorker;
    worker->moveToThread(&workThread);
    connSigAngSlots();
    workThread.start();
    emit SIG_CONECTSERVER();
}

SocketThreadCtrler::~SocketThreadCtrler()
{
    workThread.quit();
    workThread.wait();
}

void SocketThreadCtrler::connSigAngSlots()
{
    connect(&workThread,SIGNAL(finished()),worker,SLOT(deleteLater()));
    connect(this,SIGNAL(SIG_CONECTSERVER()),worker,SLOT(connectServer()),Qt::QueuedConnection);
    connect(this,SIGNAL(SIG_WRITEMSG(QByteArray&)),worker,SLOT(writeMsg(QByteArray&)));
    connect(worker,SIGNAL(Sig_LoginStatus(bool)),this,SLOT(EmitSigCheckLogin(bool)));
}


void SocketThreadCtrler::login(QString acnt, QString passwd)
{
    //如何给login专门开一个线程
    SMessage1 msg1(acnt, passwd);
    emit SIG_WRITEMSG(msg1.getMsg());
}

void SocketThreadCtrler::EmitSigCheckLogin(bool loginStatus)
{
    emit SIG_CHECKLOGIN(loginStatus);
}

socketWorker.h

    #ifndef SOCKETWORKER_H
    #define SOCKETWORKER_H

    #include <QObject>
    #include <QTcpSocket>

    #include "messagefactory.h"
    #include "rmessage.h"
    #include "message.h"
    #include "auxfuncset.h"
    #include "smessage.h"

    class SocketWorker : public QObject
    {
        Q_OBJECT
    private:
        static const quint16 serverPort=12345;
        static const QString serverAddr;
        QTcpSocket sock;

    public:
        explicit SocketWorker(QObject *parent = 0);
        void WorkerEmitSigLogin(bool loginStatus);
    private:
        bool isServerMsg();
        quint32 getMsgLen();
        void getMsg(quint32 msgLen, QByteArray& msgBytes);

    signals:
        void Sig_LoginStatus(bool loginStatus);
    public slots:
        void connectServer();
        void writeMsg(QByteArray&Msg);
        void procMsg();


    //private:
    };

    #endif // SOCKETWORKER_H

socketWorker.cpp

#include "header/backend/communication/socketworker.h"
const QString SocketWorker::serverAddr("127.0.0.1");



SocketWorker::SocketWorker(QObject *parent) : QObject(parent)
{

}


void SocketWorker::connectServer()
{
    QString tmp=serverAddr;
    sock.connectToHost(tmp,serverPort);
    connect(&sock,SIGNAL(readyRead()) ,this, SLOT(procMsg()));
}


void SocketWorker::writeMsg(QByteArray& Msg)
{
    sock.write(Msg);
//    QAbstractSocket will start sending data automatically
//    once control goes back to the event loop
    sock.flush();
}

void SocketWorker::procMsg()
{
    if(!isServerMsg()) return;

    quint32 msgLen=0;
    msgLen=getMsgLen();
    if(0 == msgLen)   return;
    QByteArray msgBytes;
    getMsg(msgLen,msgBytes);
    RMessage* msg = MessageFactory::createMessage(msgBytes);
    msg->process(this);
    delete msg;
}

bool SocketWorker::isServerMsg()
{
    //MSGHEADER
    quint32 msgHead=0;
    while(AuxFuncSet::readQuint32(&sock, msgHead))
    {
        if(msgHead == Message::MSGHEADER)
        {
            return true;
        }
    }
    return false;
}

quint32 SocketWorker::getMsgLen()
{
    while(sock.bytesAvailable()<sizeof(quint32));
    quint32 msgLen=0;
    AuxFuncSet::readQuint32(&sock,msgLen);
    return msgLen;
}

void SocketWorker::getMsg(quint32 msgLen, QByteArray& msgBytes)
{
    while(sock.bytesAvailable()<msgLen);
    msgBytes = sock.read(msgLen);
}

void SocketWorker::WorkerEmitSigLogin(bool loginStatus)
{
    emit Sig_LoginStatus(loginStatus);
}

编译器提供的错误消息是

QObject:无法为不同线程中的父级创建子级。 (Parent是QTcpSocket(0xb988c8),父线程是QThread(0xb93528),当前线程是QThread(0x8dfe2c)

从我的调试中,我发现关键部分是信号插槽连接部分导致此问题。 具体来说,有四个连接语句。 即,

connect(&workThread,SIGNAL(finished()),worker,SLOT(deleteLater()));
connect(this,SIGNAL(SIG_CONECTSERVER()),worker,SLOT(connectServer()),Qt::QueuedConnection);
connect(this,SIGNAL(SIG_WRITEMSG(QByteArray&)),worker,SLOT(writeMsg(QByteArray&)));
connect(worker,SIGNAL(Sig_LoginStatus(bool)),this,SLOT(EmitSigCheckLogin(bool)));

但只有中间的两个语句会导致这个错误。具体来说,如果我删除了中间的两个语句,即

连接(在此,SIGNAL(SIG_CONECTSERVER()),工人,SLOT(ConnectServer的()),Qt的:: QueuedConnection);     连接(在此,SIGNAL(SIG_WRITEMSG(的QByteArray&安培)),工人,SLOT(writeMsg(的QByteArray&安培;)));

然后没有错误。

所以我很困惑。一个半小时后,我仍然没有找到有效的解决方案和合理的解释。所以我认为我需要帮助。谢谢你。

0 个答案:

没有答案