qt线程

2023-11-20

qt4.7 之前的线程操作

代码
需要重写一个类,继承QTread

class mythread:public QThread
{
  Q_OBJECT  //必须加,否则出现一些奇怪问题
public:
  	mytherad();
 protected:
 	void run();
 signals:
    sigDone();
}

void run()
{ QThread::sleep(5);
emit sigdone();
}

如何启动子线程?
主线程中加入这个子线程的头文件,然后定义一个mythread对象 myt;
通过一个函数 myt.start(); 就会启动。当子线程完成操作的时候,可以向父进程发出一个信号,主线程里收到这个信号交给某个函数处理
也就是connect把两个连接起来

这里有个堵塞的方法
如果mythread有个变量,让子进程去修改这个变量,主进程里while一直判断这个变量是否被修改,当子进程被修改了,主进程继续向下进行

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:某个类继承QThread,在这个类里重写run方法,run方法里是想让子线程想要执行的内容
在主线程里面新建这个类的一个对象,然后对象.start() 将会执行
然后一些其他的就是执行完了可以传递信号回到主进程,让主进程里的某个槽函数进行后续的处理

qt4.7 之后的线程操作

代码

特点:灵活的指定一个线程对象的线程入口函数

多线程使用注意事项
1.业务对象,构造的时候不能指定父对象
2.子线程中不能处理ui窗口(ui相关的类)
3.子线程中只能处理一些数据相关的操作,不能涉及窗口

主线程:

OtherTread类包含:
信号:结束信号
槽函数:子线程进程进行工作的函数

主线程包含:
子线程的头文件
信号:发出子线程开始工作的函数
槽函数:接收子线程完成工作的函数
QThread *qt;
函数 发送要子线程开始工作的函数
app里面:
OtherTread *otherqt =new OtherTread();
qt=new QThread ();
otherqt->moveToThread(qt)
qt->start();
connnect(this,SIGNAL(让子线程开始的函数),otherqt ,SLOT(子线程工作的函数))
connect(子线程完成与当前的某个槽函数连接)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:
和上面一样,新建一个想要执行逻辑的类的对象,再新建一个QThread对象 第一个对象->moveToThread(进程对象) 然后在父进程里面就控制了这个新写的类对象的进程,让QThread对象启动,这时的启动并没有真正的启动,需要用信号槽机制发送信号以及绑定需要执行的函数

这样做的目的是可以将任意的对象选择性的交给任意的进程对象。

子线程的关闭

一般:
可以用信号槽的方式将窗口析构与子进程销毁连接上
connect(this, &class的名::destroyed,this,&class的名::一个槽函数)
这个槽函数里面
{
子线程对象.quit()
子线程对象.wait() //等待线程的工作完成
}

需要注意的是,前提是子线程的工作已经运行完
而且这个子线程是新建的线程对象,并非某个class的对象

下面代码的问题: 局部对象t在start后就会被销毁,同时成员变量 i 也会被销毁,然而线程还在运行,非法访问已经被销毁的变量
在这里插入图片描述
同步型线程设计

在析构函数中先调用wait()函数,强制等到线程运行结束
这种设计适合 线程生命期相对较短的情形

SyncThread::~SyncThread()
{
    wait(); // 等待线程结束才析构
 
    qDebug() << "SyncThread::~SyncThread() destroy thread object";
}

异步型线程设计

在 run() 中最后调用 deleteLater() 函数 ,线程体函数主动申请销毁线程对象
这种设计适合线程生命期不可控,需要长时间运行于后台情形

void AsyncThread::run()
{
    qDebug() << "void AsyncThread::run() tid = " << currentThreadId();
 
    for(int i=0; i<3; i++)
    {
        qDebug() << "void AsyncThread::run() i = " << i;
 
        sleep(1);
    }
 
    qDebug() << "void AsyncThread::run() end";
 
    deleteLater(); // 通知销毁当前线程对象 void QObject::deleteLater () [slot]
}

进程同步

比如有个加法运算(加法运算类里有三个值,前两个值是要运算的数,第三个值是他们加后的结果,第三个值默认为0)
在主进程里新建三个子进程让他们执行各自的加法运算
最后在主进程里面将这三个对象的第三个值也就是结果再加起来

在这里重点说明一下:只要一个类继承了QThread 而且还重写了run方法 如果在某个地方有三个这个类的对象,那么在调用各个对象的start后,那么将会是用子进程进行处理的,不再是顺序的调用了,哪个进程先执行完无法获悉

如果想要同步,就需要用的wait(0
这里注意wait和sleep的区别
sleep()方法的作用是 让当前正在执行的线程休眠指定的毫秒数
wait()方法
在这里插入图片描述
这个图片是说在哪里对某个对象调用wait,哪里会等待那个对象执行完毕
比如上面有个对象a执行了加法运算,那么再调用a.wait()便是等待a完成以后再向下进行,因此说,上面说的那个堵塞的方法是极其愚蠢的

线程锁

QMutex中的关键成员函数
void lock()
当锁空闲时,获取锁并执行
当锁被获取,则自身会堵塞并等待锁被释放
void unlock()
释放锁
需要注意的是:同一把锁的加锁和释放锁必须在同一线程中出现

伪代码例子


#include <QtCore/QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QDebug>
static QMutex g_mutex;  // 线程锁
static QString g_store; // 仓库
class Producer : public QThread
{
protected:
    void run()
    { int count = 0;
        while(true)
        {
            g_mutex.lock();
            g_store.append(QString::number((count++) % 10));
            qDebug() << objectName() << " : " + g_store;
            g_mutex.unlock();
            msleep(1);
        }
    }
};
 
class Customer : public QThread
{
protected:
    void run()
    {
        while( true )
        {
            g_mutex.lock();
 
            if( g_store != "" )
            {
                g_store.remove(0, 1);
 
                qDebug() << objectName() << " : " + g_store;
            }
 
            g_mutex.unlock();
 
            msleep(1);
        }
    }
};
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
 
    Producer p;
    Customer c;
 
    p.setObjectName("Producer");
    c.setObjectName("Customer");
   p.start();
    c.start();
    return a.exec();
}

上述可以看出要先有一把锁mutex,然后对于临界资源加这把锁,对于临界资源加锁并非临界资源有特定的方法,换种说法是临界资源感知不到锁的存在,只是逻辑上加上锁了,此外,每一个临界资源都有特定的一把锁,不能把一个mutex逻辑上给多个临界资源加锁
且需要注意的是,如果用while判断,每次在while结尾需要加上让自身睡上几秒,不要让while一直运行

信号量

操作系统学习的时候,对于信号量和锁会有下面这种体会
在这里插入图片描述

伪代码
QSemaphore g_sem_free(5); // 5个可生产资源
QSemaphore g_sem_used(0); // 0个可消费资源
生产者
g_sem_free.acquire(); g_sem_free信号量减一 acquire获取不到会在这里堵塞
… 主要逻辑段
g_sem_used.release(); g_sem_used信号量 加一
消费者
g_sem_used.acquire();
… 主要逻辑段
g_sem_free.release();

#include <QtCore/QCoreApplication>
#include <QThread>
#include <QSemaphore>
#include <Qdebug>
 
const int SIZE = 5;
unsigned char g_buff[SIZE] = {0}; 
 
QSemaphore g_sem_free(SIZE); // 5个可生产资源
QSemaphore g_sem_used(0);    // 0个可消费资源
 
// 生产者生产产品
class Producer : public QThread
{
protected:
    void run()
    {
        while( true )
        {
            int value = qrand() % 256;
 
            // 若无法获得可生产资源,阻塞在这里
            g_sem_free.acquire();
 
            for(int i=0; i<SIZE; i++)
            {
                if( !g_buff[i] )
                {
                    g_buff[i] = value;
 
                    qDebug() << objectName() << " generate: {" << i << ", " << value << "}";
 
                    break;
                }
            }
 
            // 可消费资源数+1
            g_sem_used.release();
 
            sleep(2);
        }
    }
};
// 消费者消费产品
class Customer : public QThread
{
protected:
    void run()
    {
        while( true )
        {
            // 若无法获得可消费资源,阻塞在这里
            g_sem_used.acquire();
 
            for(int i=0; i<SIZE; i++)
            {
                if( g_buff[i] )
                {
                    int value = g_buff[i];
 
                    g_buff[i] = 0;
 
                    qDebug() << objectName() << " consume: {" << i << ", " << value << "}";
 
                    break;
                }
            }
 
            // 可生产资源数+1
            g_sem_free.release();
 
            sleep(1);
        }
    }
};
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
 
    Producer p1;
    Producer p2;
    Producer p3;
 
    p1.setObjectName("p1");
    p2.setObjectName("p2");
    p3.setObjectName("p3");
 
    Customer c1;
    Customer c2;
 
    c1.setObjectName("c1");
    c2.setObjectName("c2");
 
    p1.start();
    p2.start();
    p3.start();
 
    c1.start();
    c2.start();
    
    return a.exec();
}

子线程与主线程通讯的方法

主要思想就是子线程发送信号,父进程提前将信号和自己的某个槽函数绑定

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

qt线程 的相关文章

  • QT 中的应用程序->处理消息?

    在 Borland 6 中 我经常使用它来解除程序操作的卡住 Application gt Processmessages 现在 对于 QT 4 8 1 我在这个外国 对我来说 QT 文档中找不到 谁能帮我 在 Qt 中 您可以使用静态函数
  • setContextProperty 和对象的 setProperty 之间的区别

    我现在真的很困惑 有什么区别 QQmlApplicationEngine engine engine rootContext setContextProperty myObject userData and object gt setPro
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 从 QML 实例化 C++ 对象会产生巨大的内存使用开销

    实例化一个QObjectC 堆中的派生类为每个对象提供了大约 160 个字节 通过注册相同的对象qmlRegisterType 用于从 QML 创建并通过以下方式动态创建对象createObject 每个对象给我 2000 多个字节 这是完
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 仅将非模态 QDialog 窗口放置在我的应用程序顶部,而不是所有应用程序顶部

    我有一个 QDialog 窗口 它应该始终位于我的应用程序顶部 它不是模态的 用户可以随时与对话框和主应用程序进行交互 使用窗口保持在顶部提示在某种程度上实现了这一点 但是 该对话框仍然位于所有其他正在运行的应用程序 例如记事本 chrom
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • 程序意外完成 - QT Creator

    我正在尝试使用 QT Creator 使用 QT 框架开发 GUI 控制台应用程序 我使用的是Windows XP 我安装了QT 4 8 3和mingw 两者均已安装 没有任何错误 然后我安装了QT Creator QT 版本 路径中的 Q
  • Qt mouseReleaseEvent() 未触发?

    我有一个显示图片的库 我们称之为 PictureGLWidget 其中 class PictureGLWidget public QGLWidget 所以 PictureGLWidget 扩展了 QGLWidget 在PictureGlWi
  • Qt:将拖放委托给子级的最佳方式

    我在 QWidget 上使用拖放 我重新实现了 DragEnterEvent dragLeaveEvent dragMoveEvent 和 dropEvent 效果很好 在我的 QWidget 中 我有其他 QWidget 子级 我希望它们
  • Qt 创建者 + MITK (Linux)

    我正在尝试使用MITK 与 Qt Creator 我已经通过 ccmake 成功编译并使用了 VTK 和 ITK 我已经编译了 MITK超级建造模式 它下载 CTK VTK ITK 等 然后我就配置好了 我已经用 make 编译了 大约两个
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • Qt - 如何粘合两个窗口并将它们移动在一起?

    就像qmmp Qt 音乐播放器ui设计一样 这两个或三个窗口实际上在同一个窗口中 因为只有一个dock图标 并且这些窗口可以一起移动并相互附着 我看了源码 好像有用QDockWidget 但我真的不知道如何获得它的细节 当您手动移动辅助窗口
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • QToolButton:更改菜单位置

    使用菜单时QToolButton菜单显示在按钮的正下方 有没有办法在按钮的左侧 右侧显示菜单 我知道这个问题不久前已得到回答 但我想为此问题添加新答案 因为接受的答案不再有效 实际上 更改 QToolButton 上的菜单位置非常容易 您需
  • 退出 Qt 程序的正确方法?

    我应该如何退出 Qt 程序 例如在加载数据文件时 发现文件损坏 并且用户需要退出该应用程序或重新启动数据文件 我是不是该 call exit EXIT FAILURE call QApplication quit call QCoreApp
  • 如何使QTableView类的restoreState()和saveState()正常工作?

    首先 我想说 我的问题已经在这里讨论过 并且这里是 https stackoverflow com questions 1163030 qt qtableview and horizontalheader restorestate 但答案并
  • QTimer 一点也不准确?

    运行在 Windows7 64 位机器上 具有非常强大的 CPU 8 核 16 线程 我使用 QTimer 以 50Hz 触发函数调用 但我最终得到了 30Hz 函数调用本身肯定需要不到 10 毫秒才能完成 整个过程发生在一个单独的线程中
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set

随机推荐

  • DHCP的配置(以华为eNSP为例)

    如有错误 敬请谅解 此文章仅为本人学习笔记 仅供参考 如有冒犯 请联系作者删除 基础知识介绍 络组建步骤 1 拓扑设计 2 IP地址规划 按照拓扑中划分的 络范围 规划 络位不同的IP地址 3 配置 1 配置各个节点的IP地址 2 路由 全
  • qbytearray的append是浅拷贝还是深拷贝_前端深拷贝和浅拷贝

    在前端攻城狮的工作实际应用中 有很多情况下在处理数据的时候 会用到数据的深拷贝和浅拷贝 例如 vue中数据是双向绑定的 页面显示依赖于从后台获取到的数据 但要将这个数据当做参数发送给另外一个接口的时候 其中有几个字段是多余的 此时 如果将原
  • 时间序列 R 07 时间序列分解 Time series decomposition

    一个时间序列可以分解为多个模型的组合 1 1 时间序列的组成 1 1 1 时间序列组成模式 三种时间序列模式 不计剩余残差部分 1 趋势Tend 比如线性趋势 先增加后降低的整体趋势 2 季节性Seasonal 以时间为固定周期 呈现循环的
  • IT项目管理个人作业8

    质量标准 量度 学历 博士以上 教学经验 5年以上 论文发布 10篇以上 逻辑表达能力 思路清晰 讲话清楚 性格 耐心 热情 同行评价 良好及以上 画出QQ图 因为数据量太少 可以推测它是符合正态分布的
  • 我的图床解决方案,超详细!

    图床就是将你的本地图片上传到相关服务商或者个人服务器 然后获取图片对应的网络访问地址 使用者可以方便快速的将图片插入到文章中 后续图片二次使用 迁移 分享都会非常简单 我之前常用的图床方案是使用Gitee的仓库来实现 我的博客 1 周刊 2
  • yaml学习

    1 yaml是专门用来写配置文件的语言 非常强大和简洁 远比json格式方便 可用之作为自动化测试框架的配置文件或者用例文件 2 使用场景 做配置文件 做测试用例 3 语法基本规则 大小写敏感 使用缩进表示层级关系 缩进的空格数目不重要 只
  • MySql笔记

    全部案例sql语句 https blog csdn net weixin 46002478 article details 109158249 视频学习地址 https www bilibili com video BV1KW411u7vy
  • 大端模式和小端模式转化

    在工作中遇到一个问题 数据是以大端模式存储的 而机器是小端模式 必须进行转换 否则使用时会出问题 一 定义 大端模式 Big Endian 数据的高字节 保存在内存的低地址中 数据的低字节 保存在内存的高地址中 小端模式 Little En
  • cube例子自带的说明文档

    Qt 5 6 Qt OpenGL Cube OpenGL ES 2 0 example Qt 5 6 0 Reference Documentation Contents Initializing OpenGL ES 2 0 Loading
  • Hibernate 知识点总结

    HIbernate最佳实践 1 使用Configuration装载映射文件时 不要使用绝对路径装载 最好的方式是通过getResourceAsStream 装载映射文件 这样Hibernate会从classpath中寻找已配置的映射文件 2
  • IDEA 消除项目结构 0%classes,0% lines covered

    1 起因 启动的时候 误点了下面的图标 2 作用 经查 这个图标的作用 用于检测代码覆盖率 在单元测试中经常被用到 以后有时间可以详细了解一下 3 解决 方法一 点击 Coverage 会出现一个 Coverage 控制台 点击红叉 No
  • 基于MATLAB BP神经网络的水果识别

    基于MATLAB BP神经网络的水果识别 一 课题实现的功能 1 原理分析 由于数字图像是唯一的特征标识符号 在经营管理中具有不可替代的作用 因此数字图像识别系统应具有很高的识别正确率 对环境光照条件 拍摄位置等因素的影响应有较大的容阈 并
  • 【平差软件学习---科傻】四、科傻二等水准平差(参数设置和in1文件讲解)

    平差软件学习 科傻 四 科傻二等水准平差 参数设置和in1文件讲解 这个算是最后一集了 也可能不是如果我想到不足的地方我会在补上一集视频 或者是文章页 总感觉自己操作的很熟练 到自己真正讲的时候就没有头绪了 不知道看到的我讲的同事会不会笑话
  • python的爬虫代码_python爬虫代码

    encoding utf 8 importreimportrequestsimporturllib2importdatetimeimportMySQLdbfrom bs4 importBeautifulSoupimportsys reloa
  • GVIM教程,GVIM使用心得

    目录 一 gvim的基础操作 1 插入字符 2 移动光标或页面 3 查找内容 4 替换 5 删除文本 6 复制粘贴 7 对文件的操作 8 多行编辑 9 选中文本 一 gvim的基础操作 以下操作均在命令模式下进行 操作中需要输入冒号则进入末
  • Java Quartz框架

    Java Quartz框架 Java Quartz是一个开源的作业调度框架 用于在Java应用程序中实现定时任务和调度功能 它提供了灵活的任务调度和执行机制 可以根据时间表或触发事件来触发任务的执行 Quartz的主要作用是简化定时任务的管
  • elasticsearch query bool nested对象 聚合

    复杂的查询 下面的查询是小编自己研究写的一个比较复杂 的语句 涉及到查query bool must 已经过滤条件term 关键词介绍 from 表示从第几条开始返回 size 表示返回的题目数大小 query 查询语句 bool must
  • 抢「.AI」域名,成了 3000 万美元的大生意

    作者 汤一涛编辑 靖宇 1848 年 一个木匠在加利福尼亚州科罗马地区的一条河中偶然发现了金箔 尽管他曾试图保守这个秘密 但是金子不会说谎 一场席卷全美的淘金热就此开始 许多人怀揣着一夜暴富的梦想涌入加利福尼亚 1847 到 1870 年间
  • tensorflow-GPU版本安装,RTX3060

    首先需要安装好pycharm和anaconda 开始安装tensorflow GPU版 一 查看版本 1 首先检查自己电脑的cudn版本 开始 gt 设置 gt 应用 gt 安装的应用 搜cuda 我的是cuda 11 6 2 查看显卡型号
  • qt线程

    qt4 7 之前的线程操作 代码 需要重写一个类 继承QTread class mythread public QThread Q OBJECT 必须加 否则出现一些奇怪问题 public mytherad protected void r