版权声明:个人学习之路,若有误,欢迎指正。其中一些博文被证明有错误的地方,最近比较忙,没时间更正,谨慎参考!! https://blog.csdn.net/y396397735/article/details/82314458
Qt界面程序通常什么情况下要使用到线程?
Qt界面程序在调用接口处理时间较长的任务时(如连接网络、复制文件等等耗时操作),界面在等待接口返回前会导致卡死。
为了不让界面卡死,可以使用一个子线程来处理耗时任务,关于QThread的线程在这里就不介绍了,本文讲的使用std::thread来快速方便解决这个问题。
解决问题思路
1、现代大部分C++编译器已经支持C++11 的自带线程类std::thread,线程随时创建,随时销毁方便。
2、QEventLoop类事件循环可用来等待线程执行完毕,并且界面不会因等待而卡死。
3、在线程任务执行结束后,可给QEventLoop对象发送一个信号,告知程序执行结束,QEventLoop对象在收到信号时退出循环,向上告知线程执行结果。
程序示例
ThreadTest界面类头文件如下:
/** @file ThreadTest.h
* @author lesliefish
* @date 2018/08/31
*/
#pragma once
#include <QPushButton>
#include <QEventLoop>
#include <QtWidgets/QWidget>
#include "ui_ThreadTest.h"
class ThreadTest : public QWidget
{
Q_OBJECT
public:
explicit ThreadTest(QWidget *parent = Q_NULLPTR);
signals:
// 线程执行结束后发送此信号
void signalRunOver();
private:
// 测试函数
void test();
private:
Ui::ThreadTestClass ui;
};
ThreadTest界面类cpp文件具体实现如下:
#include "ThreadTest.h"
#include <thread>
ThreadTest::ThreadTest(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
// 绑定信号 点击按钮后执行test函数
connect(ui.pushButton, &QPushButton::clicked, [&]
{
test();
});
}
/** @fn ThreadTest::test
* @brief 测试函数 点击界面按钮后执行
* @return void
*/
void ThreadTest::test()
{
// 假设需要知道线程的执行结果runResult
bool runResult{ false };
// 定义一个loop对象
QEventLoop loop;
// 绑定信号 在loop收到界面发送的signalRunOver信号后,退出循环
connect(this, &ThreadTest::signalRunOver, &loop, &QEventLoop::quit);
// 声明一个线程,处理耗时任务 传入匿名函数 在声明testThread后直接开启一个线程执行匿名函数体
std::thread testThread([&]
{
// runResult = 连接网络 、拷贝文件、等等耗时操作 实际执行的任务放在这个位置执行
// 执行耗时操作完成后 发出信号 告知线程执行结束
emit signalRunOver();
});
// 分离线程 让其自生自灭(销毁线程)
testThread.detach();
// 在此处执行循环 等待线程的执行结果
loop.exec();
// 以上线程执行完成后执行以下代码
if (!runResult)
{
// 处理结果 整个过程界面不会卡死
}
}
如上,按以上操作可以保证界面在执行耗时任务时不会卡顿。
完整源码带ui文件路径:
https://github.com/lesliefish/Qt/tree/master/Core/Qt%E5%92%8CC%2B%2B11thread