当前位置: 首页 > news >正文

【Qt】多线程

线程创建

自定义线程类

#ifndef CUSTOMETHREAD_H
#define CUSTOMETHREAD_H#include <QObject>
#include <QThread>
#include "add.h"class CustomeThread : public QThread
{Q_OBJECT
public:// Bind the thread kernel function.explicit CustomeThread(Add*& addPtr);private:// Run the thread kernel functionvirtual void run() override;
private:Add* m_addFuc {nullptr};
};#endif // CUSTOMETHREAD_H

主函数

#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();//Concrator the thread kernel function object.Add* ladd = new Add(); CustomeThread* thread = new CustomeThread(ladd);thread->start();return a.exec();
}

结果:

Current thread id:  0x36d0
current Thread:  0x7f50
100  +  200  =  300

计算的核心函数在子线程中进行。
通过创建一个线程的controller 类,绑定线程执行的kernel函数。然后再子线程的run函数里执行 kernel 函数。

改进

上面的程序中 kernel 函数和 执行线程并没有在同一个线程下,所以虽然Qt通过跨线程调用的机制,在子线程调用成功了,但是终究是一种不安全的方式,所以,为了保险起见,需要将 kernel函数再移入子线程。

#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();//Concrator the thread kernel function object.Add* ladd = new Add(); CustomeThread* thread = new CustomeThread(ladd);ladd->moveToThread(thread);thread->start();return a.exec();
}

线程循环

事件循环

int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);return a.exec();
}

上面的 a.exec() 即让程序进入系统的事件循环,事件循环是一个特殊的死循环,其作用如下:

  • 阻塞程序,使得线程一直执行。
  • 在循环内部可以不断的监听系统发来的信号,并作出反应。
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QObject>#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();Add* ladd = new Add();CustomeThread* thread = new CustomeThread(ladd);ladd->moveToThread(thread);thread->start();QTimer* timer = new QTimer();QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));return a.exec();
}

在这个例子里面,使用了一个定时器,向子线程里的 kernel 对象发送信号,出发 add() 槽函数。但是最后并没有触发到。一个原因是: 此时的 ladd 已经在子线程了, 直接连接信号槽,大部分时候只能在信号和槽函数在同一个线程时生效。比如,我们不把 ladd移动到子线程中:

int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();Add* ladd = new Add();CustomeThread* thread = new CustomeThread(ladd);// Not move ladd to subthread!!!!//ladd->moveToThread(thread);thread->start();QTimer* timer = new QTimer();QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));return a.exec();
}
Main thread id:  0x5628
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200
Current Thread:  0x5628
100  +  100  =  200

如何子线程的对象发信号?

可以这样连接信号和操

QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()), Qt::QueuedConnection);

向子线程发了信号,子线程就能接受吗?

但是发现即时这样也不能向子线程发信号,这是因为子线程中的run函数并没有调用事件循环,此时子线程已经结束退出了,所以可以在子线程的run函数中增加事件循环

void CustomeThread::run()
{exec();
}
Main thread id:  0x5384
Current Thread:  0x1638
100  +  100  =  200
Current Thread:  0x1638

自定义事件循环

http://www.lryc.cn/news/127043.html

相关文章:

  • 腾讯云GPU服务器GN7实例NVIDIA T4 GPU卡
  • 3. 爬取自己CSDN博客列表(自动方式)(分页查询)(网站反爬虫策略,需要在代码中添加合适的请求头User-Agent,否则response返回空)
  • 利用HTTP代理实现请求路由
  • 深度学习(36)—— 图神经网络GNN(1)
  • 深入理解JVM——垃圾回收与内存分配机制详细讲解
  • 基于SSH框架实现的管理系统(包含java源码+数据库)
  • 图像识别代做服务:实现创新应用的新契机
  • Coreutils工具包,Windows下使用Linux命令
  • 神经网络基础-神经网络补充概念-13-python中的广播
  • HDFS原理剖析
  • css学习2(利用id与class修改元素)
  • wsl2(debian)安装python的不同版本例如3.8
  • Python教程(9)——Python变量类型列表list的用法介绍
  • springboot+VUE智慧公寓管理系统java web酒店民宿房屋住宿报修信息jsp源代码
  • 神经网络基础-神经网络补充概念-36-dropout正则化
  • Go语言基础之变量和常量
  • Spring Boot 项目实现 Spring AOP
  • Baumer工业相机堡盟工业相机如何通过BGAPISDK设置相机的固定帧率(C#)
  • js拼接字符串
  • 神经网络基础-神经网络补充概念-37-其他正则化方法
  • 掌握Python的X篇_36_定义类、名称空间
  • 回归预测 | MATLAB实现GRU门控循环单元多输入多输出
  • 数据结构--拓扑排序
  • 算法竞赛备赛之搜索与图论训练提升,暑期集训营培训
  • Linux驱动入门(6.2)按键驱动和LED驱动 --- 将逻辑电平与物理电平分离
  • CentOS系统环境搭建(十四)——CentOS7.9安装elasticsearch-head
  • 设计HTML5图像和多媒体
  • 基于YOLOv8模型和Caltech数据集的行人检测系统(PyTorch+Pyside6+YOLOv8模型)
  • Flutter 宽高自适应
  • LeetCode 0833. 字符串中的查找与替换