QT 初识多线程

这篇具有很好参考价值的文章主要介绍了QT 初识多线程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.QThread线程基础

QThread是Qt线程中有一个公共的抽象类,所有的线程类都是从QThread抽象类中派生的,需要实现QThread中的虚函数run(),通过start()函数来调用run函数。

    void run()函数是线程体函数,用于定义线程的功能。

    void start()函数是启动函数,用于将线程入口地址设置为run函数。

    void terminate()函数用于强制结束线程,不保证数据完整性和资源释放。

    QCoreApplication::exec()总是在主线程(执行main()的线程)中被调用,不能从一个QThread中调用。在GUI程序中,主线程也称为GUI线程,是唯一允许执行GUI相关操作的线程。另外,必须在创建一个QThread前创建QApplication(or QCoreApplication)对象。

    当线程启动和结束时,QThread会发送信号started()finished(),可以使用isFinished()和isRunning()来查询线程的状态。

从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::deleteLater()槽。 
    使用wait()来阻塞调用的线程,直到其它线程执行完毕(或者直到指定的时间过去)。

    静态函数currentThreadId()currentThread()返回标识当前正在执行的线程。前者返回线程的ID,后者返回一个线程指针。

    要设置线程的名称,可以在启动线程之前调用setObjectName()。如果不调用setObjectName(),线程的名称将是线程对象的运行时类型(QThread子类的类名)。

应用程序的线程称为主线程,额外创建的线程为工作线程。一般在主线程里面创建工作线程,并调用 start() 开始执行工作线程的任务。start()会在内部调用run()函数,进入工作线程的循环,在 run() 函数里调用 exit() 或 quit() 可以结束线程的事件循环,或在主线程里调用 terminate() 强制结束线程。

                                                            QThread类的主要接口
类型 函数 功能
       公共函数 bool  isFinished () 线程是否结束
bool  isRunning () 线程是否正在运行
Priority  priority () 返回线程的优先级
void setPriority (Priority  priority) 设置线程的优先级
void exit(int returnCode=0) 退出事件的循环,退出码为returnCode ,0表示成功,否则表示有错误
bool wait(unsigned long time) 阻止线程执行,直到线程结束(从run函数返回),或等待时间超过time毫秒
公共槽函数 void  quit() 退出线程的事件循环,并返回代码0,等效于exit()
void  start(Priority  priority) 内部调用run()函数开始执行线程,操作系统根据priority参数进行调度终止线程的运行,但不是立即结束线程,而是等待操作系统结束线程。使用terminate()之后应使用wait()
void terminate()
 信号 void  finished() 在线程结束时发射此信号
void start() 在线程开始执行、run()函数被调用之前发射此信号
静态公共函数 int  idealThreadCount() 返回系统上能运行的线程的理性个数
void  msleep(unsigned long msecs)  强制当前线程休眠msecs毫秒
void sleep(unsigned long secs) 强制当前线程休眠secs秒
void  usleep(unsigned long usecs)  强制当前线程休眠uecs微秒
保护函数 virtual void run() start()调用run()函数开始线程任务的执行,所以在run()函数里实现线程的任务功能
int exec() 由run()函数调用,进入线程的时间循环,等待exit()退出

2.小案例

threaddlg.h
#ifndef THREADDLG_H
#define THREADDLG_H
#define  MAXSIZE 5
#include "workthread.h"
#include <QDialog>
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class Threaddlg; }
QT_END_NAMESPACE

class Threaddlg : public QDialog
{
    Q_OBJECT

public:
    Threaddlg(QWidget *parent = nullptr);
    ~Threaddlg();

private:
    Ui::Threaddlg *ui;
    QPushButton  *startBtn;
    QPushButton  *stopBtn;
    QPushButton  *quitBtn;

    WorkThread *workThread[MAXSIZE];

public  slots:
    void  slotStart();
    void  slotStop();



};
#endif // THREADDLG_H

threaddlg.cpp

#include "threaddlg.h"
#include "ui_threaddlg.h"
#include<QHBoxLayout>
Threaddlg::Threaddlg(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Threaddlg)
{
    ui->setupUi(this);
    setWindowTitle(QStringLiteral("线程"));

    startBtn=new QPushButton(QStringLiteral("线程"));
    stopBtn=new QPushButton(QStringLiteral("停止"));
    quitBtn=new QPushButton(QStringLiteral("退出"));
    QHBoxLayout *mainLayout=new QHBoxLayout(this);
    mainLayout->addWidget(startBtn);
    mainLayout->addWidget(stopBtn);
    mainLayout->addWidget(quitBtn);

    connect(startBtn,SIGNAL(clicked()),this,SLOT(slotStart()));
    connect(stopBtn,SIGNAL(clicked()),this,SLOT(slotStop()));
    connect(quitBtn,SIGNAL(clicked()),this,SLOT(close()));

}

Threaddlg::~Threaddlg()
{
    delete ui;
}

void Threaddlg::slotStart()
{
    for(int i=0;i<MAXSIZE;i++){
        workThread[i]=new WorkThread; //创建指定数目的WorkThread线程,并将其保存在指针数组workThread中
    }
    for(int i=0;i<MAXSIZE;i++){
        workThread[i]->start();//调用QThread基类start函数,此函数将启动run,使线程开始真正运行
    }
    startBtn->setEnabled(false);
    stopBtn->setEnabled(true);
}

void Threaddlg::slotStop()
{
     for(int i=0;i<MAXSIZE;i++){
          workThread[i]->terminate();//terminate函数不会立刻终止这个线程,该线程何时终止取决于操作系统的调度策略
          workThread[i]->wait();//使线程阻塞等待直到退出或超时
     }
     startBtn->setEnabled(true);
     stopBtn->setEnabled(false);
}

WorkThread.h
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
#include <QtDebug>
class WorkThread : public QThread
{
public:
    WorkThread();

protected:
    void  run();
};

#endif // WORKTHREAD_H

 WorkThread.cpp

 #include "workthread.h"

WorkThread::WorkThread()
{

}

void WorkThread::run()
{
    while(true)
    {
        for(int n=0;n<10;n++)
            qDebug()<<n<<n<<n<<n<<n<<n<<n;
    }
}

结果:

          1个线程                                                                                                           5个线程

 QT 初识多线程,qt,开发语言QT 初识多线程,qt,开发语言

 可以看出,一个线程输出是顺序打印的,5个线程也就是多线程的输出结果是乱码打印的

犯了一个很低级的错误

报错为:

QT 初识多线程,qt,开发语言

原来是因为:    对了,就是clicked没有加括号

QT 初识多线程,qt,开发语言

2.案例2

多线程(这里是2个)并发操作,分别负责打印基数和偶数

ui设计器设计控件如下:

QT 初识多线程,qt,开发语言

my_thread.h

#ifndef MY_THREAD_H
#define MY_THREAD_H
#include <QObject>
#include <QThread>
class my_thread : public QThread  //线程一
{
    Q_OBJECT
public:
    my_thread() {stopped=false;}
    void stop();

protected:
    void run();

private:
    bool  stopped;

};

class my_thread_2 : public QThread //线程二
{
    Q_OBJECT
public:
    my_thread_2() {stopped=false;}
    void stop();

protected:
    void run();

private:
    bool  stopped;

};


#endif // MY_THREAD_H

my_thread.cpp

#include "my_thread.h"
#include<QDebug>
void my_thread::run()
{
    int i=0;
    while(!stopped)
    {
        qDebug()<<"MyThread:"<<i;
        msleep(1000);//线程休眠1s
        i+=2;
    }
    stopped=false;
}
void my_thread::stop()
{
    stopped=true;
}

void my_thread_2::run()
{
    int i=1;
    while(!stopped)
    {
        qDebug()<<"MyThread:"<<i;
        msleep(1000);//线程休眠1s
        i+=2;
    }
    stopped=false;
}
void my_thread_2::stop()
{
    stopped=true;
}

widght.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <my_thread.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::Widget *ui;
    my_thread thread;
    my_thread_2 thread2;
};
#endif // WIDGET_H

widght.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
   thread.start();
   ui->pushButton->setEnabled(false);
   ui->pushButton_2->setEnabled(true);
}

void Widget::on_pushButton_2_clicked()
{
   if(thread.isRunning())
   {
       thread.stop();
   }
   ui->pushButton->setEnabled(true);
   ui->pushButton_2->setEnabled(false);
}

void Widget::on_pushButton_3_clicked()
{
    thread2.start();
    ui->pushButton_3->setEnabled(false);
    ui->pushButton_4->setEnabled(true);
}

void Widget::on_pushButton_4_clicked()
{
    if(thread2.isRunning())
    {
        thread2.stop();
    }
    ui->pushButton_3->setEnabled(true);
    ui->pushButton_4->setEnabled(false);
}

结果:首先点击启动线程一,再点击线程二,然后点击结果线程一,在结束线程二(顺序随便)这里我操作后的结果为:

QT 初识多线程,qt,开发语言文章来源地址https://www.toymoban.com/news/detail-698127.html

到了这里,关于QT 初识多线程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 13-1_Qt 5.9 C++开发指南_多线程及QThread 创建多线程程序_ThreadSignal

    一个应用程序一般只有一个线程,一个线程内的操作是顺序执行的,如果有某个比较消耗时间的计算或操作,比如网络通信中的文件传输,在一个线程内操作时,用户界面就可能会冻结而不能及时响应。这种情况下,可以创建一个单独的线程来执行比较消耗时间的操作,并与

    2024年02月14日
    浏览(45)
  • 【Visual Studio】Qt 的实时绘图曲线功能,使用 C++ 语言,配合 Qt 开发串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 战斗背景:做了个串口接收界面,用来接收传输过来的信号。但是光用数字显示太单调,需要用图线显示出来。 战略目标:干掉它。 战术路线:Qt 绘图可以使用 Qt Charts,先了解

    2024年02月11日
    浏览(49)
  • 【VisualStudio】使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月10日
    浏览(76)
  • 基于Linux C++多线程服务器 + Qt上位机开发 + STM32 + 8266WIFI的智慧无人超市

    针对传统超市购物车结账排队时间长、付款效率低的问题,提出了一种更符合现代社会人们购物方式-基于RFID的自助收银系统。习惯了快节奏生活的人们都会选择自助收银机结账,理由显而易见:自助收银机结账很方便,几乎不用排队,也不用近距离和收银员接触,在防疫时

    2024年03月10日
    浏览(81)
  • Qt简单使用与初识

    🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风翻盘 。 🛸 qt学习专栏 : qt学习专栏 家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重

    2024年01月21日
    浏览(31)
  • QT(7)-初识委托

    委托是Qt中的一种机制,用于在Qt模型/视图架构中处理特定类型的数据。委托提供了一种方便的方法来定制特定类型的数据的显示和编辑。 委托可以做以下事情: 编辑特定类型的数据: 通过创建编辑器来编辑特定类型的数据,例如日期,数值等. 渲染特定类型的数据: 通过定制单元

    2024年01月25日
    浏览(29)
  • C++系列三:QT初识2

    目录 代码参考: 前言: 我可没说放弃

    2024年02月10日
    浏览(41)
  • Qt Quick系列(9)—初识画布

    🚀作者:CAccept 🎂专栏:Qt Quick 画布元素的基本思想是使用上下文2D对象( ctx )渲染路径。上下文2D对象包含必要的图形功能,而画布充当绘图画布。 在QML中, 画布元素(canvas element)充当了绘制的容器 。2D绘制对象( ctx )提供了实际绘制的方法。绘制需要在 onPaint 中完成

    2024年02月12日
    浏览(35)
  • 初识Qt-无法解析的外部符号

    跟着教程学习QT, 第一个对象树就出现bug,自己建立一个QPushButton的类, 建立好类之后,在Widget.cpp中添加按钮: MyPushButton *btn2=new MyPushButton(this); btn2-setParent(this); btn2-setText(\\\"MY Button\\\"); btn2-move(200,100); 结果一直提示: MyPushButton是一个无法解析的外部符号! 解决方案: 打开.pro文

    2024年01月23日
    浏览(40)
  • 【VisualStudio】基于 Visual Studio 使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月15日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包