我是qt的初学者。我在qt文档中采用了QThread Class推荐的方式。 文档中使用的方法如下。
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
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&安培;)));
然后没有错误。
所以我很困惑。一个半小时后,我仍然没有找到有效的解决方案和合理的解释。所以我认为我需要帮助。谢谢你。