QT每日一练day29:QT中的多线程探究
一.未使用多线程,则w0先运行完后,w1才开始运行
运行结果(GIF动图):
main.cpp
xiaowen_QT_day29.pro
QT+=widgets
SOURCES += \main.cpp
main.cpp
#include<QApplication>
#include<QDebug>
#include<QThread>
class Work
{public:Work(const QString& name):_objectName(name){}void working(){for(int i=0;i<5;i++){qDebug()<<"working"<<_objectName<<i<<endl;QThread::sleep(1);//1秒打印1次}}
private:QString _objectName;
};int main(int argc,char** argv)
{QApplication app(argc,argv);Work w0("w0"),w1("w1");w0.working();w1.working();return app.exec();
}
二.QT中第一种创建线程的方式——派生QThread类。
2.1 这里先注释掉前部分代码,运行单独的派生QThread类WorkThread:
main.cpp
运行结果(GIF动图):
2.2 撤销前半部分的注释,尝试运行两个线程:
main.cpp
运行结果(GIF动图):
2.3 线程ID打印:
main.cpp
运行结果(GIF动图):
2.4 打印线程运行状态、回收线程:
main.cpp
运行结果:
2.5 线程中exec的问题:
main.cpp
运行结果(GIF动图):
2.6 附代码:
xiaowen_QT_day29
QT+=widgets
SOURCES += \main.cpp
main.cpp
#include<QApplication>
#include<QDebug>
#include<QThread>class Work
{public:Work(const QString& name):_objectName(name){}void run(){working();}void working(){for(int i=0;i<10;i++){qDebug()<<"working"<<_objectName<<i<<QThread::currentThreadId()<<endl;QThread::sleep(1);//1秒打印1次}}
private:QString _objectName;
};class WorkThread:public QThread
{public:WorkThread(const QString& name,QObject *parent=NULL):QThread(parent),_objectName(name){}void run(){working();this->exec();}void working(){for(int i=0;i<10;i++){qDebug()<<"working"<<_objectName<<i<<QThread::currentThreadId()<<endl;QThread::sleep(1);}}
private:QString _objectName;
};int main(int argc,char** argv)
{QApplication app(argc,argv);Work w0("w0");WorkThread w1("w1");w1.start();qDebug()<<"thread is running"<<w1.isRunning()<<endl;//打印线程运行状态w0.working();qDebug()<<"thread is running"<<w1.isRunning()<<endl;//打印线程运行状态w1.quit();qDebug()<<"thread wait finish"<<w1.wait(5000)<<endl;//打印线程运行状态return app.exec();
}
三.QT中第二种创建线程的方式
- 继承 QObject
- 实例化一个QThread对象
- 实现槽函数.
- QObject子类对象通过moveToThread将自己放到线程QThread对象中.
- 调用QThread对象的start函数启动线程
- 必须通过发射信号来让槽函数在线程中执行,发射的信号存放在线程exec()消息队列中。
例:
test.h
#ifndef TEST_H
#define TEST_H
#include <QThread>
#include <QDebug>
class MyWork : public QObject
{Q_OBJECT
public slots:void workSlot(){qDebug() << "QThread begin" << endl;qDebug() << "child thread" << QThread::currentThreadId() << endl;QThread::sleep(5);qDebug() << "QThread end" << endl;}
};
#endif // TEST_H
main.cpp
#include<QApplication>
#include<QDebug>
#include<QThread>
#include"test.h"
int main(int argc, char** argv)
{qDebug() << "main thread" << QThread::currentThreadId() << endl;QApplication app(argc, argv);QThread thread;MyWork work;work.moveToThread(&thread);QObject::connect(&thread, SIGNAL(started()), &work, SLOT(workSlot()));thread.start();QThread::sleep(6);qDebug() << "thread is runing" << thread.isRunning() << endl;thread.quit(); //调用quit让线程退出消息循环,否则线程一直在exec循环中thread.wait(); //调用完quit后紧接着要调用wait来回收线程资源qDebug() << "thread is runing" << thread.isRunning() << endl;return app.exec();
}
运行结果(GIF动图):
需要特别注意的是:
子线程中的槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过quit()退出线程exec()。
QObject派生类对象,若要调用moveToThread,不能指定一个主线程父对象托管内存。
QWidget的对象及派生类对象都只能在GUI主线程运行,不能使用moveToThread移到子线程中,即使没有指定父对象。
多线程对象内存释放:
既然QObject对象无法托管内存对象,那么到底是先释放线程对象,还是先释放这个QObject对象?
先把QObject在线程循环中释放(使用QObject::deleteLater函数),然后QThread::quit,然后QThread::wait。
例:
mywork.h
#ifndef MYWORK_H
#define MYWORK_H
#include <QThread>
#include <QDebug>
class MyWork : public QObject
{Q_OBJECT
public:~MyWork() { qDebug() << __FUNCTION__ << endl; }
public slots:void workSlot(){qDebug() << "Work begin" << QThread::currentThreadId() << endl;QThread::sleep(2);qDebug() << "work end" << endl;}void otherWorkSlot(){qDebug() << "otherWork begin" << QThread::currentThreadId() << endl;QThread::sleep(2);qDebug() << "otherWork end" << endl;}
};
#endif // MYWORK_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mywork.h"
class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = 0);~Widget();
private:QThread *_thread;MyWork *_myWork;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QPushButton>
#include "mywork.h"
#include <QThread>
#include <QHBoxLayout>
Widget::Widget(QWidget *parent): QWidget(parent)
{_myWork = new MyWork;_thread = new QThread(this);_myWork->moveToThread(_thread);_thread->start();QPushButton *pb0 = new QPushButton("work", this);QPushButton *pb1 = new QPushButton("pb", this);QHBoxLayout *hBox = new QHBoxLayout(this);hBox->addWidget(pb0);hBox->addWidget(pb1);this->setLayout(hBox);/*发射信号给在另外一个线程的对象的队列中*/connect(pb0, SIGNAL(clicked()), _myWork, SLOT(workSlot()));connect(pb1, SIGNAL(clicked()), _myWork, SLOT(otherWorkSlot()));/*推荐用法释放内存*///connect(_thread, SIGNAL(finished()), _myWork, SLOT(deleteLater()));
}
Widget::~Widget()
{_myWork->deleteLater(); //一定要在QThread线程退出之前_thread->quit();_thread->wait();
}
main.cpp
#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
运行结果(GIF动图):
QT每日一练day29:QT中的多线程探究相关推荐
- QT每日一练day4:ubuntu中使用QT
(本文主要是为了说明QT的跨平台特性) 一.安装QT sudo apt-get install qt5-default qtcreator cmake 二.打开QT 可以点击图标或命令行方式: 三 ...
- QT每日一练day1:第一个程序
参考博文:Qt常见类.窗口类继承关系树图 QT每日一练(1):第一个程序 最终效果(GIF动图): step1: step2: step3: step4: step5: step6: step7: s ...
- QT每日一练day26:绘制图片
一.第一阶段 发现上述图片没有显示全!!!!! 二.第二阶段 设置宽高比,平滑转换 运行结果(GIF动图): 发现上述图片在数次缩放后会产生失真!!!!! 三.第三阶段 为了避免图像缩放过程中产生失真 ...
- QT每日一练day21:鼠标事件
一.第一阶段--鼠标点击和释放事件 运行结果(GIF动图): MouseEvent.pro #------------------------------------------------- # # ...
- QT每日一练day5:QLabel和按钮窗口打印功能
运行:输入字符串然后按print按钮 project.pro QT+=widgets HEADERS += \widget.hSOURCES += \widget.cpp \main.cpp widg ...
- QT每日一练day2:day1优化以及QT内存管理机制
QT中的继承关系 day1优化 一般我们不直接用QWidget来实例化对象,用它的派生类来生成对象,main函数中一般不写太多代码,都是在派生类的构造函数中进行窗口的初始化.布局.设置.其子窗口设 ...
- QT每日一练day27:绘制不规则窗体
注:本文本来应该是以一个不规则的图片作为历程的,,忘记了!!!! 一.第一阶段:隐藏窗体框架 运行结果(GIF动图): widget.cpp 二.第二阶段:将窗口设置为透明 运行结果(GIF动 ...
- QT每日一练day25:触发绘画事件
运行结果(GIF动图): widget.cpp 附代码: xiaowen_QT_day25.pro QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT ...
- QT每日一练day24:绘画事件
一.第一阶段 设置线条粗细 二.第二阶段:设置笔的样式 如:虚线 三.第三阶段:绘制矩形 四.第四阶段:设置颜色 轮廓颜色 笔刷颜色 笔刷样式 五.第五阶段:绘制其他形状图像和文字 六.第六阶段:图像 ...
最新文章
- 使用代理网络配置maven,显示导入失败的原因
- NHibernate+MySql (erro 解决方法)
- Django中一个项目使用多个数据库(原生sql 的使用,亲测)
- SQLite大漏洞!所有Chromium浏览器中招,安卓iOS应用也受殃及
- android之日志库logger
- mysql 复杂类型_MySQL 复杂数据类型之JSON数据
- 计算机专业新手博客,【转载】学计算机必读献给计算机专业大一新生(1)
- Qpython 获取Android gps信息
- hdu acm1157
- C语言实现SM4加解密
- 14个PLC入门基础知识
- awd的批量脚本 pwn_记一次AWD反杀之旅
- 100 offer:为什么你不需要做一名全栈工程师?
- 西游记中揭示的深刻人生哲理
- 深大校园网掉线/Drcom掉线/使校园网保持在线V2.0+Linux端Drcom登录方法(宿舍区教学区)
- 苹果wifi网速慢怎么办_家里网速慢如何解决 提高WiFi网速方法【详解】
- 计算机or笔记本,笔记本or台式机 这几款戴尔主机性能上没得挑
- 如何投资股票型基金?什么时间买?买什么?
- IPD电源REL-70-4006
- ios-自定义Storyboard与UIViewController