Qt下QThread用法学习之多线程
[html]
//tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include "tcpthread.h"
#include<QTcpServer>
class TcpServer:public QTcpServer
{
Q_OBJECT
public:
explicit TcpServer(QObject *parent=0);
//Object obj;
signals://更新UI
void bytesArrived(qint64,qint32,int);
protected:
void incomingConnection(int socketDescriptor);
};
#endif
[html]
//tcpserver.cpp
#include "tcpserver.h"
TcpServer::TcpServer(QObject *parent):
QTcpServer(parent)
{
}
//在incomingConnection中新建一个tcpsocket线程,并完成相应的信号连接。
void TcpServer::incomingConnection(int socketDescriptor)
{
TcpThread *thread=new TcpThread(socketDescriptor,this);
qDebug()<<"server thread:"<<QThread::currentThreadId();
connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));//关闭线程
connect(thread,SIGNAL(bytesArrived(qint64,qint32,int)),this,SIGNAL(bytesArrived(qint64,qint32,int)));//接收数据
thread->start();
}
[html]
#ifndef TCPTHREAD_H
#define TCPTHREAD_H
#include <QThread>
#include<QTcpSocket>
#include<QtNetwork>
class QFile;
class QTcpSocket;
class Object:public QObject {
Q_OBJECT
public: Object(int socketDescriptor);
public:
int socketDescriptor;
qint64 bytesReceived;
qint64 byteToRead;
qint32 TotalBytes;
QTcpSocket *tcpSocket;
QHostAddress fileNameIp;//文件名Ip部分
QFile *localFile;
QByteArray inBlock;//读取缓存
signals:
void error(QTcpSocket::SocketError socketError);
void bytesArrived(qint64,qint32,int);
void receiveSgl(QTcpSocket*);
public slots:
void receiveFile();
};
class TcpThread:public QThread
{
Q_OBJECT
public:
TcpThread(int socketDescriptor,QObject *parent);
~TcpThread();
void run();
public slots:
//void receiveFile();
signals:
void bytesArrived(qint64,qint32,int);
private:
int socketDescriptor;
//Object obj;
};
#endif
[html]
#include "tcpthread.h"
#include<QtGui>
#include<QtNetwork>
TcpThread::TcpThread(int socketDescriptor,QObject *parent):
QThread(parent),socketDescriptor(socketDescriptor)
{
//bytesReceived=0;
//QObject::connect(this, SIGNAL(receiveSgl(QTcpSocket*)), &obj, SLOT(slot(QTcpSocket*)));
}
Object::Object(int socketDescriptor):socketDescriptor(socketDescriptor)
{
tcpSocket=new QTcpSocket;
bytesReceived=0;
if(!tcpSocket->setSocketDescriptor(socketDescriptor)){
emit error(tcpSocket->error());
return;
}
qDebug()<<socketDescriptor;
QObject::connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(receiveFile()));
}
TcpThread::~TcpThread()
{
quit();
wait();
deleteLater();
}
void TcpThread::run()
{
Object obj2(socketDescriptor);
obj2.moveToThread(this);
QObject::connect(&obj2,SIGNAL(bytesArrived(qint64,qint32,int)),this,SIGNAL(bytesArrived(qint64,qint32,int)),Qt::BlockingQueuedConnection);//接收数据
// qDebug()<<socketDescriptor;
////这是重中之重,必须加Qt::BlockingQueuedConnection!
//这里困扰了我好几天,原因就在与开始没加,默认用的Qt::AutoConnection。
//简单介绍一下QT信号与槽的连接方式:
//Qt::AutoConnection表示系统自动选择相应的连接方式,如果信号与槽在同一线程,就采用Qt::DirectConnection,
//如果信号与槽不在同一线程,将采用Qt::QueuedConnection的连接方式。
//Qt::DirectConnection表示一旦信号产生,立即执行槽函数。
//Qt::QueuedConnection表示信号产生后,将发送Event给你的receiver所在的线程,postEvent(QEvent::MetaCall,...),
//slot函数会在receiver所在的线程的event loop中进行处理。
//Qt::BlockingQueuedConnection表示信号产生后调用sendEvent(QEvent::MetaCall,...),
//在receiver所在的线程处理完成后才会返回;只能当sender,receiver不在同一线程时才可以。
//Qt::UniqueConnection表示只有它不是一个重复连接,连接才会成功。如果之前已经有了一个链接(相同的信号连接到同一对象的同一个槽上),那么连接将会失败并将返回false。
//Qt::AutoCompatConnection与QT3保持兼容性
//说明一下,对于任何的QThread来说,其线程只存在于run()函数内,其它的函数都不在线程内,所以此处要采用Qt::BlockingQueuedConnection,
//因为当SOCKET有数据到达时就会发出readyRead()信号,但是此时可能之前的receiveFile()还未执行完毕,之前使用的Qt::AutoConnection,
//结果传输大文件的时候就会出错,原因就在于只要有数据到达的时候,就会连接信号,但是数据接收还没处理完毕,而Qt::BlockingQueuedConnection会阻塞
//此连接,直到receiveFile()处理完毕并返回后才发送信号。
qDebug()<<"run thread:"<<QThread::currentThreadId();
//connect(tcpSocket,SIGNAL(readyRead()),this,SIGNAL(receiveSgl(tcpSocket)));
// connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(receiveFile()),Qt::BlockingQueuedConnection);
exec();
}
void Object::receiveFile()
{
qDebug(
补充:综合编程 , 其他综合 ,