QT——C++ 多线程05

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

一、创建多线程的方式

QT创建(使用)多线程的方式有三种。

  1. 直接创建QThread 对象,重写run方法,最后调用start方法启动线程。
  2. 通过调用QObject类提供的moveToThread方法实现
  3. 线程池

(一)方式一:

如果需要向run传入参数,或者返回执行结果,可以通过信号和槽机制实现

  • mywork.h
#ifndef MYWORK_H
#define MYWORK_H

#include <QObject>
#include <QThread>

/**
 *    @class   mywork.h
 *
 *    @brief   工作线程
 *
 *
 *    @author:   lihua
 *    @date:     2022-10-25  15:53
 */
class MyWork : public QThread
{
    Q_OBJECT
public:
    explicit MyWork(QThread *parent = nullptr);

signals:
    //信号由子线程发出,主线程接收(子线程返回执行结果给主线程)
    void signalWork(int result);

public slots:
    //信号由主线程发出,子线程接收(主线程传入参数给子线程)
    void slotWork(int num);

    // QThread interface
protected:
    void run();

private:
    int num = 0;

};

#endif // MYWORK_H

  • mywork.cpp
#include "mywork.h"
#include <QDebug>

MyWork::MyWork(QThread *parent) : QThread(parent)
{

}

void MyWork::slotWork(int num)
{
    //调用槽函数
    qDebug()<< "子线程的槽函数被调用"<<num;
    this->num = num;

}

/**
 * @brief 主线程传一个初始值num给子线程,子线程在num的基础上加100
 *
 * @param  run没有参数,num是通过槽函数获取的
 *
 * @return  run没有返回值将计算结果通过槽函数返回给主线程
 */
void MyWork::run()
{

    qDebug()<< "运行子线程<<" << QThread::currentThread();

    //主线程给一个初始值num
    int num = this->num;



    int result = num +100;

    //发出信号,订阅了此信号的订阅者的槽函数会被回调,将计算结果通过槽函数返回给主线程
    qDebug()<< "结果:"<<result;
    emit signalWork(result);


}

  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "mywork.h"

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    //子线程
    MyWork *thread;

    // 计算结果
    int result;

signals:
    //信号
    void signalMain(int num);

public slots:
    //槽函数
    void slotMain(int result);

};



#endif // MAINWINDOW_H

  • mainwindow.cpp
#include "mainwindow.h"
#include "mywork.h"
#include "ui_mainwindow.h"

#include <QThread>
#include <QDebug>

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

    qDebug()<< QThread::currentThread();

    thread = new MyWork();


    //订阅signalMain信号,并指定回调函数。
    connect(this,&MainWindow::signalMain,thread,&MyWork::slotWork);

    //订阅signalWork信号,并指定回调函数
    //connect(thread,&MyWork::signalWork,this,&MainWindow::slotMain); 也可以用lamda实现
    connect(thread,&MyWork::signalWork,this,[=](int result){

        this->result = result;
        qDebug()<< "result="<<this->result;
    });

    //发出一个信号,将10通过槽函数slotWork传递给run
    emit signalMain(10);

    thread->start();


}

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

void MainWindow::slotMain(int result)
{
    this->result = result;

    qDebug()<< "result="<<this->result;
}

(二)方式二:

更改此对象及其子对象的线程关联。如果对象具有父对象,则无法移动该对象。事件处理将在targetThread中继续。
如果targetThread为零,则此对象及其子对象的所有事件处理都将停止。

请注意,对象的所有活动计时器都将重置。计时器首先在当前线程中停止,然后在targetThread中重新启动(以相同的间隔)。因此,在线程之间不断移动对象会无限期地延迟计时器事件。

在更改线程关联之前,QEvent::ThreadChange事件被发送到此对象。您可以处理此事件以执行任何特殊处理。请注意,任何发布到此对象的新事件都将在targetThread中处理。

警告:此函数不是线程安全的;当前线程必须与当前线程关联性相同。换句话说,此函数只能将对象从当前线程“推”到另一个线程,不能将对象从任意线程“拉”到当前线程

  • mywork1.h
#ifndef MYWORK1_H
#define MYWORK1_H

#include <QObject>

class MyWork1 : public QObject
{
    Q_OBJECT
public:
    explicit MyWork1(QObject *parent = nullptr);

    //工作函数
    void work();
signals:
    void curNumber(int  num);

public slots:
};

#endif // MYWORK1_H

  • mywork1.cpp
#include "mywork1.h"

#include <QThread>
#include <QDebug>

MyWork1::MyWork1(QObject *parent) : QObject(parent)
{

}

void MyWork1::work()
{
    qDebug()<< "子线程对象地址:"<<QThread::currentThread() ;

    int num = 0;
        while(1)
        {
            emit curNumber(num++);
            if(num == 1000)
            {
                break;
            }
            QThread::usleep(1);
        }
        qDebug() << "run() 执行完毕, 子线程退出...";
}

  • 核心代码
void MainWindow::testThread()
{
    QThread *thread = new QThread();

    MyWork1 *work = new MyWork1();

    //注意这个方法是QObject提供的,将对象从当前线程“推”到另一个线程运行
    work->moveToThread(thread);
    thread->start();

    //不能直接调用,直接调用还是主线程运行
    //work->work();
    //通过槽机制运行才能将对象交给targetThread运行。
    connect(ui->pushButton,&QPushButton::clicked,work, &MyWork1::work);

    connect(work,&MyWork1::curNumber,this,[=](int num){
        ui->textBrowser->setText(QString::number(num));
    });
}

(三)方式三:

QThreadPool类管理QThreads的集合。
QThreadPool管理和重新设计单个QThread对象,以帮助减少使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象,可以通过调用globalInstance()来访问该对象。
要使用QThreadPool线程之一,请将QRunnable子类化并实现run()虚拟函数。然后创建该类的对象并将其传递给QThreadPool::start()文章来源地址https://www.toymoban.com/news/detail-500536.html

#include "mywork2.h"
#include <QDebug>
#include <QThread>
MyWork2::MyWork2()
{

}

void MyWork2::run()
{
    qDebug()<< "线程池方式使用多线程。"<<QThread::currentThread();

}

/**
 * @brief 线程池测试
 *
 * @param
 * @param
 *
 * @return
 */
void MainWindow::testThreadPool()
{
    //获取线程池,同时设置最大线程数。
    QThreadPool::globalInstance()->setMaxThreadCount(2);
    MyWork2 *work = new MyWork2();

    QThreadPool::globalInstance()->start(work);
    
}

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

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

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

相关文章

  • 线程创建的三种方式

    目录 1. Thread类 2. Runnable接口 3. Callable接口 4. 线程的生命周期 新建  就绪 运行 阻塞 等待 结束 继承Thread类的方式创建线程 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务 创建Thread类的子类,即创建了线程对象 调用线程对象的

    2024年02月09日
    浏览(42)
  • PHP的curl有三种Post请求数据的方式

    今天要讲的HTTP请求头的Content-Type字段,就是在curl发送post请求的时候需要指定以何种方式来请求数据,常用的有3类: 1、form-data 。就是 multipart/form-data 使用表单的方式来发送数据 是curl采用的默认发送方式。请求数组类型的格式。 Content-Type: multipart/form-data 2、x-www-form-urlenco

    2024年02月11日
    浏览(72)
  • Java多线程 - 创建的三种方式介绍

    什么是线程 ? 线程(thread)是一个程序内部的一条执行路径。 我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径。 程序中如果只有一条执行路径,那么这个程序就是单线程的程序。 什么是多线程 ? 多线程是指从软硬件上实现多条执行流程的技术。 方式一

    2024年02月20日
    浏览(45)
  • Java并发(三)----创建线程的三种方式及查看进程线程

    例如: 输出 注意:这里通过 @Slf4j 注解打印的日志 把【线程】和【任务】(要执行的代码)分开 Thread 代表线程 Runnable 可运行的任务(线程要执行的代码) 例如: 输出 Java 8 以后可以使用 lambda 精简代码 小结 方法1 是把线程和任务合并在了一起,方法2 是把线程和任务分开

    2023年04月24日
    浏览(47)
  • 高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式

    Java中的多线程是一个同时执行多个线程的进程。线程是一个轻量级的子进程,是最小的处理单元。多进程和多线程都用于实现多任务处理。 但是,一般使用多线程而不是多进程,这是因为线程使用共享内存区域。它们不分配单独的内存区域以节省内存,并且线程之间的上下

    2024年02月13日
    浏览(39)
  • 【Java面试题】线程创建的三种方式及区别?

    继承Thread类,子类重写run()方法,调用子类的strat()启动线程。 实现Runnable接口,实现run()方法,调用对象start()启动线程。 实现Callable接口,实现call()方法,用FutureTask()封装实现类。使用FutureTask对象作为Thread对象调用start()启动线程,调用FutureTask对象的get()

    2024年02月12日
    浏览(49)
  • Verilog的三种描述方式(结构化描述、数据流描述、行为级描述对电路功能的描述有三种方式:结构化描述、数据流描述、行为级描述

    Verilog的三种描述方式(结构化描述、数据流描述、行为级描述对电路功能的描述有三种方式:结构化描述、数据流描述、行为级描述。三种描述方式抽象级别不同,各有优缺点,相辅相成,需要配合使用。 目录 一、结构化描述 1、概念 2、特点 3、示例 真值表: 电路抽象:

    2024年02月04日
    浏览(64)
  • Springboot中使用线程池的三种方式

    前言 多线程是每个程序员的噩梦,用得好可以提升效率很爽,用得不好就是埋汰的火葬场。 这里不深入介绍,主要是讲解一些标准用法,熟读唐诗三百首,不会作诗也会吟。 这里就介绍一下springboot中的多线程的使用,使用线程连接池去异步执行业务方法。 由于代码中包含详

    2024年02月08日
    浏览(46)
  • Qt中使用OpenGL的三种方式

    1.继承QOpenGLWidget并重写基类如下函数  通过使用QOpenGLContext来操作OPENGL函数   2. 继承QOpenGLFunctions类可直接使用OPENGL函数   直接使用OPENGL函数  3. 继承QOpenGLWidget 与QOpenGLExtraFunctions  在OPENGL中使用Shader 最终效果 

    2024年02月14日
    浏览(51)
  • 13-1_Qt 5.9 C++开发指南_多线程及QThread 创建多线程程序_ThreadSignal

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

    2024年02月14日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包