大家好,又见面了,我是你们的朋友全栈君。
为什么要是用多线程?
多线程的使用主要是为了处理比较耗时的过程。多线程的实现可以通过两种方式实现
分别是:1.继承QThread实现多线程2.继承QObject实现多线程(由于继承QObject的多线程实现方法更加灵活,Qt官方推荐使用该方法实现多线程)。这里将采用第二种方式实现多线程
多线程实现过程
1.创建一个继承于QObject的自定义线程类,用来处理比较耗时的功能。
相关函数:
void setFlag(bool flag = true); //用于设置线程是否启动
void ConnectServer();//用于连接到服务器
槽函数:注意:槽函数应该用“private slots:”来修饰
void dowork();//线程处理函数
void ConnectedSuccess();//用来响应QTcpSocket的conneted()信号
void readData();//用来响应QTcpSocket的readyRead()信号
信号函数:注意:信号函数应该用 “signals:”来修饰
void signal_connectsuccess(QString)//用来向主线程发送链接成功信息
void signal_back(QString)//用来向主线程发送从服务器获取的数据
2.在主线程中创建一个子线程
QThread *mThread = new QThread(this);
3.创建一个自定义线程对象
TcpSocketThread *mTcpSocketThread = new TcpSocketThread ();
注意:这里创建的对象不能指定父对象,因为不能移动已经具有父类的对象,mThread可以看做是mTcpSocketThread 的父类
4.将子线程类对象移动到子线程容器中
mTcpSocketThread .moveToThread(mThread);
5.连接主线程与子线程之间的信号和槽函数(这里用的是QT4.8.6,QT5版本的connect函数则不同)
主线程——>子线程
connect(this,SIGNAL(StartThread()),mTcpSocketThread, SLOT(doWork()));
子线程——–>主线程
connect(mTcpSocketThread,SIGNAL(signal_connectsuccess(QString)),this,SLOT(slot_handle_state(QString)));
connect(mTcpSocketThread,SIGNAL(signal_back(QString)),this,SLOT(slot_handle_data(QString)));
使用connect不成功有可能是如下原因
这里需要注意 信号函数和槽函数的参数列表应该一致
使用信号槽,需要在类中声明 Q_OBJECT宏
槽函数应该用“private slots:”来修饰
信号函数应该用 “signals:”来修饰
6.子线程使用完毕应该及时回收并销毁
mThread->quit();
mThread->wait()
相关代码
主线程类:tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include
#include
#include
#include
#include
#include “ui_tcpclient.h”
#include “tcpsocketthread.h”
class TCPClient : public QWidget
{
Q_OBJECT
public:
explicit TCPClient(QWidget *parent = 0, Qt::WFlags flags = 0);
~TCPClient();
private:
Ui::TCPClientClass ui;
TCPSocketThread *mTcpSocketThread; //子线程
QThread *mThread; //线程管理器
private slots:
//处理链接状态信号
void slot_handle_state(QString);
//处理数据信号
void slot_handle_data(QString);
private slots:
//链接服务器
void on_Btn_Connect_clicked();
//启动线程
void on_Btn_start_clicked();
//断开链接
void on_Btn_DisConnect_clicked();
signals:
void StartThread();
};
#endif // TCPCLIENT_H
主线程类:tcpclient.cpp
#include “tcpclient.h”
TCPClient::TCPClient(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
//创建子线程
mTcpSocketThread = new TCPSocketThread();
//创建线程管理
mThread = new QThread();
//将子线程移动到线程管理器中
mTcpSocketThread->moveToThread(mThread);
//信号槽事件
connect(this,SIGNAL(StartThread()),mTcpSocketThread, SLOT(doWork()));//开启子线程
connect(mTcpSocketThread,SIGNAL(signal_connectsuccess(QString)),this,SLOT(slot_handle_state(QString)));//处理子线程信号
connect(mTcpSocketThread,SIGNAL(signal_back(QString)),this,SLOT(slot_handle_data(QString)));
}
TCPClient::~TCPClient()
{
}
void TCPClient::on_Btn_Connect_clicked()
{
//若线程正在运行,返回
if(mThread->isRunning()==true) return;
//线程状态设置为开启
mTcpSocketThread->setFlag(false);
//开启线程
mThread->start();
//启动了线程,并未进入线程
//发送信号,进入线程
emit StartThread();
ui.Lbl_ClientState->setText(“Connected Success!”);
}
void TCPClient::on_Btn_start_clicked()
{
}
void TCPClient::on_Btn_DisConnect_clicked()
{
//若线程已关闭,返回
if(mThread->isRunning()!=true) return;
//线程状态设置为关闭
mTcpSocketThread->setFlag(true);
mThread->quit();
mThread->wait();
ui.Lbl_ClientState->setText(“Not Connected”);
}
void TCPClient::slot_handle_state(QString str)
{
ui.Lbl_ClientState->setText(str);
}
void TCPClient::slot_handle_data(QString str)
{
ui.textEdit->append(str);
}
自定义线程类 tcpsocketthread.h
#ifndef TCP_SOCKET_THREAD
#define TCP_SOCKET_THREAD
#include
#include
#include
#include
#include
#include
#include
enum MessageType{ConnectRequest,ConnectSuccess,DisConnect,DataRequest/*……….*/};//消息请求类型
class TCPSocketThread :public QObject
{
Q_OBJECT
public:
explicit TCPSocketThread(QObject *parent = 0);
~TCPSocketThread(void);
private:
bool isStop; //线程是否停止
bool isConnected; //服务器是否链接
QTcpSocket *mTcpSocket;
quint16 nextBlockSize;
public:
//设置状态
void setFlag(bool flag = true);
private:
//链接服务器
void ConnectServer();
private slots:
//线程处理函数
void doWork();
//链接成功
void ConnectedSuccess();
//获取数据
void readData();
signals:
//链接状态信号
void signal_connectsuccess(QString);
//数据信号
void signal_back(QString);
};
#endif
自定义线程类 tcpsocketthread.cpp
#include “tcpsocketthread.h”
TCPSocketThread::TCPSocketThread(QObject *parent /* = 0 */):QObject(parent)
{
isStop = false;
isConnected = false;
mTcpSocket = new QTcpSocket(this);
nextBlockSize = 0;
connect(mTcpSocket,SIGNAL(connected()),this,SLOT(ConnectedSuccess()));
connect(mTcpSocket,SIGNAL(readyRead()),this,SLOT(readData()));
}
TCPSocketThread::~TCPSocketThread(void)
{
}
void TCPSocketThread::doWork()
{
while(!isStop)
{
if(!isConnected) ConnectServer();
QByteArray data;
QDataStream out(&data,QIODevice::WriteOnly);//======out
out<
mTcpSocket->write(data);
mTcpSocket->waitForReadyRead();
}
}
void TCPSocketThread::setFlag(bool flag)
{
isStop = flag;
}
void TCPSocketThread::ConnectServer()
{
QString ip = “127.0.0.1”;
qint16 port = 40404;
mTcpSocket->connectToHost(QHostAddress(ip),port);
mTcpSocket->waitForConnected();
}
void TCPSocketThread::ConnectedSuccess()
{
isConnected = true;
QString str = “connected success!”;
emit signal_connectsuccess(str);
}
void TCPSocketThread::readData()
{
//这里的代码都无关紧要
//…….
emit signal_back(str);
//…….
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197717.html原文链接:https://javaforall.cn