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()<<"obj thread:"<<QThread::currentThreadId();  
    QDataStream in(tcpSocket); 
    if(bytesReceived<sizeof(qint32)) 
    { 
        if(tcpSocket->bytesAvailable()>=sizeof(qint32)) 
        { 
            in.setByteOrder(QDataStream::LittleEndian);//linux系统是大端 
            in>>TotalBytes; 
            TotalBytes+=4; 
            qDebug()<<TotalBytes; 
 
            bytesReceived+=sizeof(qint32); 
            fileNameIp = tcpSocket->peerAddress(); 
            quint16 port = tcpSocket->peerPort(); 
            localFile = new QFile(fileNameIp.toString()+(tr(".%1").arg(port))) ; 
            if(!localFile->open(QFile::WriteOnly)) 
            { 
     
            } 
        } 
    } 
    if(bytesReceived<TotalBytes){ 
        byteToRead=tcpSocket->bytesAvailable(); 
        bytesReceived+=byteToRead; 
        inBlock=tcpSocket->readAll(); 
        qDebug()<<"BytesReceived is :"<<bytesReceived; 
        localFile->write(inBlock); 
        inBlock.resize(0); 
    } 
    emit bytesArrived(bytesReceived,TotalBytes,socketDescriptor); 
    if(bytesReceived==TotalBytes){ 
        localFile->close(); 
        qDebug()<<bytesReceived; 
        //emit TcpThread::finished(); 
        QApplication::restoreOverrideCursor(); 
    } 
 


[html] 
#ifndef WIDGET_H 
#define WIDGET_H 
 
#include <QWidget> 
#include "tcpthread.h" 
#include "tcpserver.h" 
 
class QDialogButtonBox; 
class QTcpSokcet; 
class QProgressBar; 
class QLabel; 
class QPushButton; 
class QTextBrowser; 
class Widget:public QWidget 

    Q_OBJECT 
public: 
    explicit Widget(QWidget *parent = 0); 
    ~Widget(); 
private: 
    TcpServer tcpServer; 
    QProgressBar *progressBar; 
    QPushButton *okBtn; 
    QPushButton *quitBtn; 
    QLabel *statuslabel; 
    QTextBrowser *textBrowser; 
private slots: 
    void okBtnClicked(); 
    void updateProgress(qint64,qint32,int); 
}; 
 
#endif 


[html] 
#include "widget.h" 
#include <QtNetwork> 
#include <QtGui> 
#include<QProgressBar> 
#include<QTextBrowser> 
Widget::Widget(QWidget *parent):QWidget(parent) 

    progressBar=new QProgressBar; 
    progressBar->setMaximum(2); 
    progressBar->setValue(0); 
 
    okBtn=new QPushButton("open"); 
    quitBtn=new QPushButton("quit"); 
    textBrowser=new QTextBrowser; 
    statuslabel=new QLabel(this); 
qDebug()<<"main thread:"<<QThread::currentThreadId();  
 
    connect(okBtn,SIGNAL(clicked()),this,SLOT(okBtnClicked())); 
    QGridLayout *mainLayout=new QGridLayout; 
    mainLayout->addWidget(okBtn,0,0,1,1,0); 
    mainLayout->addWidget(quitBtn,0,1,1,1,0); 
    mainLayout->addWidget(textBrowser,1,0,5,2,0); 
    mainLayout->addWidget(progressBar,6,0,1,2,0); 
    mainLayout->addWidget(statuslabel,7,0,1,1,0); 
    setLayout(mainLayout); 

 
Widget::~Widget() 

 

 
void Widget::okBtnClicked() 

    okBtn->setEnabled(false); 
    QApplication::setOverrideCursor(Qt::WaitCursor); 
 
    while(!tcpServer.isListening()&&!tcpServer.listen(QHostAddress::Any,9001)) 
    { 
        QMessageBox::StandardButton ret = QMessageBox::critical(this,tr("回环"), 
        tr("无法开始测试:%1.").arg(tcpServer.errorString()),QMessageBox::Retry|QMessageBox::Cancel); 
        if(ret==QMessageBox::Cancel) 
        return; 
    } 
 
    statuslabel->setText(tr("监听端口:%1").arg("12345"));   
    connect(&tcpServer,SIGNAL(bytesArrived(qint64,qint32,int)),   
    this,SLOT(updateProgress(qint64,qint32,int)));   
 }   
 
void Widget::updateProgress(qint64 bytesReceived, qint32 TotalBytes, int socketDescriptor)   
{   
    progressBar->setMaximum(TotalBytes);   
    progressBar->setValue(bytesReceived);   
    statuslabel->setText(tr("已接收 %1MB").arg(bytesReceived)); /// (1024 * 1024)));   
    textBrowser->setText(tr("现在连接的socket描述符:%1").arg(socketDescriptor));   
}  


[html] 
#include "widget.h" 
#include <QApplication> 
#include<QtGui> 
 
 
int main(int argc,char **argv) 

    //QTranslator oTranslator; 
    /*QFile file("qt_zh_CN.qm"); 
    bool b = file.exists(); 
    if(b) 
        oTranslator.load("qt_zh_CN.qm"); 
    else 
        qDebug()<<"Error\n"; 
    */ 
     
    //oTranslator.load("imagewindow_la");    
 
    QApplication app(argc,argv); 
    //app.installTranslator(&oTranslator); 
 
    QTextCodec::setCodecForTr(QTextCodec::codecForName("System")); 
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("System")); 
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("System")); 
 
    Widget imageWin; 
    imageWin.setFont(QFont("wqy-zenhei",14,QFont::Normal)); 
    imageWin.resize(400,300); 
    imageWin.show(); 
    return app.exec(); 

 

转载于:https://www.cnblogs.com/MingZznet/articles/3211041.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值