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

Qt多线程1

 

Qt的多线程对于设计并行程序来说很有帮助,但是多线程因为其固有的一些特性,会导致程序会出现各种隐患,尤其是类设计不好的时候尤为严重。

这里我们将详细介绍一下Qt的多线程技术,包括如何制作一个线程安全的类。

首先我们先写一个简单的例子:

首先,我们再次使用一个类DebugText ,该类继承自DebugWidget类:

#pragma once
#ifndef _DEBUGWIDGET_H__
#define _DEBUGWIDGET_H__
#include <QWidget>
#include <qtextedit.h>
#include <qlayout.h>
#include <QPainter>
class DebugWidget : public QWidget {
	Q_OBJECT

public:
	
	~DebugWidget();
	

protected:
	DebugWidget(QWidget * parent = Q_NULLPTR);
private:

};

#endif



#include "debugwidget.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
#include <fstream>

DebugWidget::DebugWidget(QWidget * parent) : QWidget(parent) {
	
	//setWindowFlags(Qt::WindowStaysOnTopHint);
	resize(1100,800);
	//setAttribute(Qt::WA_DeleteOnClose, true);

}

DebugWidget::~DebugWidget() {

}
#include <QWidget>
#include <qtextedit.h>
#include <qlayout.h>
#include "debugwidget.hpp"
class DebugText : public DebugWidget {
	Q_OBJECT

public:

	~DebugText();
	void addContents(const QString& s1);
	static DebugText* getDebugText();


private:
	QTextEdit *ShowDebugArea;
	QHBoxLayout *qlayout;

	DebugText(DebugWidget * parent = Q_NULLPTR);


};
extern DebugText *dt;

#endif





#include "debugtext.hpp"
#include "debugwidget.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
#include <fstream>

static DebugText *dt = NULL;

DebugText::DebugText(DebugWidget * parent) : DebugWidget(parent) {

	
	qlayout = new QHBoxLayout(this);
	ShowDebugArea = new QTextEdit(this);
	ShowDebugArea->setFontPointSize(18);
	qlayout->setAlignment(Qt::AlignCenter);
	qlayout->addWidget(ShowDebugArea);

	show();
}

DebugText::~DebugText() {
}

void DebugText::addContents(const QString& s1)
{
	ShowDebugArea->append(s1);
	show();
}

DebugText* DebugText::getDebugText() {
	if (dt == NULL)
		dt = new DebugText;
	return dt;
}

该类是自己定义的输出类,作用是开一个窗口,然后在上面显示东西。该类在前面自定义调试器的部分已经说过了。

我们的多线程方式采用继承多线程类,然后里面的run,即在另一个线程里启动的函数。注意该函数不用直接调用,直接使用QThread::start(),就会自动调用该函数。

#pragma once
#ifndef __MULTITHREAD_H__
#define __MULTITHREAD_H__
#include <QThread>

class MultiThread : public QThread {
	Q_OBJECT

public:
	MultiThread(QObject * parent = Q_NULLPTR);
	~MultiThread();

	void run();
private:
	

};
#include "multithread.hpp"
#include "Debugtext.hpp"

MultiThread::MultiThread(QObject * parent) : QThread(parent) {
	
}

MultiThread::~MultiThread() {
	
}

void MultiThread::run()
{
	int i = 10;
	while (i--) {
		DebugText::getDebugText()->addContents("aaaaaaa");
		
	}

}

注意,DebugText类只是一个普通的类,它并没有任何使用多线程的机制。

#include "multithread.hpp"
#include <QApplication>
#include "Debugtext.hpp"
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);

	MultiThread  mythread;
        mythread.start();
	
	int i = 10;
	while (i--) {
		DebugText::getDebugText()->addContents("bbbbbb");

	}	
	
	return a.exec();
}

然后运行。惊喜发生了:内存访问出错。

这是为什么呢?因为我们的DebugText的核心函数就是在TextEdit控件里添加显示字符串,而如果两个线程同时去访问了这个对象,则就会出现访问错误的情况。

我们改改主函数:

#include "multithread.hpp"
#include <QApplication>
#include "Debugtext.hpp"
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);

	MultiThread  mythread;

	//mythread.terminate();
	int i = 10;
	while (i--) {
		DebugText::getDebugText()->addContents("bbbbbb");

	}	
	mythread.start();
	//QThread::sleep(100);
	return a.exec();
}

这样,就可以发现,我们先打印了一堆bbbbbbb,然后又打印了一堆aaaaaaa,

但是这样好像并没有什么意义,因为我们是想同时让bbbbbbb和aaaaaaaa被打印出来。否则就是先执行一个再执行另一个,这就不是多线程了。

为了实现可以多个线程同时调用DebugText,我们必须对这个DebugText加入多线程的机制,这会在下一节进行介绍。

相关文章:

  • Qt多线程2
  • 基于QT的文件管理软件编写 系列 引言
  • 基于QT的文件管理软件编写 系列 1
  • python安装tensorflow
  • 机器学习之 Keras默认数据集/模型存放位置
  • 从零开始写出分而治之查找最大子列表的算法
  • 学机器学习必备的一些python句法基础 1 列表 元组 字典 条件语句
  • 学机器学习必备的一些python句法基础 2 循环
  • 学机器学习必备的一些python句法基础 3 函数 内建函数 模块 包 全局局部变量
  • 学机器学习必备的一些python句法基础 4 Python类和对象
  • 学机器学习必备的一些python句法基础 5 文件读写
  • 算法 后缀表达式计算加减乘除
  • 算法题分析 出入栈问题
  • 算法 队列问题(浙大数据结构视频作业)
  • 算法 PAT真题 Pop Sequence 分析思路以及实现 1
  • 【个人向】《HTTP图解》阅后小结
  • co模块的前端实现
  • JavaScript函数式编程(一)
  • React系列之 Redux 架构模式
  • webgl (原生)基础入门指南【一】
  • 从零搭建Koa2 Server
  • 回顾 Swift 多平台移植进度 #2
  • 记录一下第一次使用npm
  • 批量截取pdf文件
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (function(){})()的分步解析
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (蓝桥杯每日一题)love
  • (十五)使用Nexus创建Maven私服
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)ABI是什么
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET 解决重复提交问题
  • .net 使用ajax控件后如何调用前端脚本
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • [ 数据结构 - C++] AVL树原理及实现
  • [20150707]外部表与rowid.txt
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Android Pro] Notification的使用
  • [Android]Android开发入门之HelloWorld
  • [Angular] 笔记 20:NgContent
  • [LeetCode] Longest Common Prefix 字符串公有前序
  • [LeetCode]Max Points on a Line
  • [Linux] CE知识随笔含Ansible、防火墙、VIM、其他服务
  • [NOSQL] Redis介绍