前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt多线程编程

Qt多线程编程

作者头像
DeROy
修改2020-09-05 22:12:46
2.1K0
修改2020-09-05 22:12:46
举报
文章被收录于专栏:编程学习基地编程学习基地

我在github仓库里面看到之前遗留的Qt_Demo,把文章相应的工程文件提交到仓库里面去,上次的简易聊天室也同步过去了,以及这篇文章的两个线程Demo。

给我个Star

https://github.com/ADeRoy/Qt_Demo

多线程开发

线程基础

GUI线程与工作线程

每个程序启动后拥有的第一个线程称为主线程,即GUI线程。QT中所有的组件类和几个相关的类只能工作在GUI线程,不能工作在次线程,次线程工作线程,主要负责处理GUI线程卸下的工作。

什么时候用到多线程?

以界面为例:所有的IO操作都要放到线程里面

  1. IO操作 QIODevice 文件IO 网络IO(套接字 eg:CAN linux下也是套接字) 串口等外设 ;因为不确定什么时候能读写完成
  2. 耗时的算法 eg: 文件压缩 信号处理

注意

线程里面尽量少用 while(1) + sleep(),尤其是while

eg:第一个例子如果用while(1),那么当线程exit(),并等待退出时wait()时不会退出线程,等待超时后会报错

QThread介绍

QThread类提供了一个与平台无关的管理线程的方法。一个QThread对象管理一个线程。QThread的执行从run()函数的执行开始,在Qt自带的QThread类中,run()函数通过调用exec()函数来启动事件循环机制,并且在线程内部处理Qt的事件。在Qt中建立线程的主要目的就是为了用线程来处理那些耗时的后台操作,从而让主界面能及时响应用户的请求操作。QThread的使用方法有如下两种:

  • QObject::moveToThread()
  • 继承QThread类

继承QThread类

程序运行后开启线程,打印100~0

Program右键添加新文件,继承QThread

添加头文件

代码语言:javascript
复制
#include <QObject>
#include <QThread>

添加宏

不添加Q_OBJECT宏无法使用信号与槽机制

代码语言:javascript
复制
Q_OBJECT

重写run函数

代码语言:javascript
复制
protected:
    virtual void run();

mythread.h文件:

代码语言:javascript
复制
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    MyThread();
protected:
    virtual void run();
private:
};
#endif // MYTHREAD_H

mythread.cpp

代码语言:javascript
复制
#include "mythread.h"
#include <QtDebug>
MyThread::MyThread()
{
    /*MyThread的构造函数任然在主线程里面*/
    qDebug()<<"MyThread::MyThread:"<<QThread::currentThreadId();
}

void MyThread::run()
{
    while(1)
    {
        qDebug()<<"MyThread::run:"<<QThread::currentThreadId();
        QThread::sleep(1);
    }
}

main.c

代码语言:javascript
复制
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "mythread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug()<<"main a.exec() :"<<QThread::currentThreadId();
    MyThread thread1;
    thread1.start();
    /*使用线程只需要再次定义线程类MyThread即可*/
//    MyThread thread2;
//    thread2.start();
    return a.exec();
}

QObject::moveToThread()

这里有一个小示例

创建的是带界面的mainwindow窗口

Program右键添加新文件,继承QObject

2

MyThread.h

代码语言:javascript
复制
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
class MyThread : public QObject
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);

signals:
    //线程向外部发出带Val值得信号
    void SendVal(int);
public slots:
    //线程工作函数
    void MyThreadWork();
};

#endif // MYTHREAD_H

MyThread.cpp

代码语言:javascript
复制
#include "mythread.h"
#include <QDebug>
#include <QThread>
MyThread::MyThread(QObject *parent) : QObject(parent){
}
void MyThread::MyThreadWork()
{
    for(int val=0;val<=100;val++)
    {
        //向外部发送信号
        emit SendVal(val);
        //睡眠一秒
        QThread::sleep(1);
        qDebug()<<val;
    }
}

mainwindow.h

代码语言:javascript
复制
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include "mythread.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
signals:
    void checkMyThread();
private slots:
    void RecvVal(int Val);
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QThread m_thread;
    MyThread m_ProgressBarVal;
};

#endif // MAINWINDOW_H

mainwindow.cpp

代码语言:javascript
复制
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->progressBar->setMaximum(100);   //设置进度条最大值
    ui->progressBar->setValue(0);       //设置进度条当前值为0
    ui->statusBar->addWidget(ui->progressBar);  //将进度条添加进状态栏MainToolBal

    m_ProgressBarVal.moveToThread(&m_thread);   //m_ProgressBarVal移动到线程中去
    m_thread.start();//开启线程
    //关联信号,当触发checkMyThread()信号时执行MyThreadWork()函数
    connect(this,SIGNAL(checkMyThread()),&m_ProgressBarVal,SLOT(MyThreadWork()));
    //关联信号,当触发SendVal()信号时执行RecvVal()函数,并将值传递过去
    connect(&m_ProgressBarVal,SIGNAL(SendVal(int)),this,SLOT(RecvVal(int)));
}

MainWindow::~MainWindow()
{
    //线程退出并等待10s
    m_thread.exit();
    m_thread.wait(1000*10);
    delete ui;
}
void MainWindow::RecvVal(int Val)
{
    //设置进度条的值
    ui->progressBar->setValue(Val);
}

void MainWindow::on_pushButton_clicked()
{
    //触发checkMyThread()信号,使MyThreadWork()工作
    emit checkMyThread();
}

End

作者 | 梦凡

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程学习基地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 多线程开发
    • GUI线程与工作线程
      • QThread介绍
        • 继承QThread类
          • Program右键添加新文件,继承QThread
          • mythread.h文件:
          • mythread.cpp
          • main.c
        • QObject::moveToThread()
          • MyThread.h
          • MyThread.cpp
          • mainwindow.h
          • mainwindow.cpp
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档