提示:欢迎小伙伴的点评✨✨,相互学习c/c++应用开发。🍳🍳🍳
博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩🚀
文章目录
- 前言
- 一、多线程及简单实例概述
- 二、效果实例
- 三、原码实例
- threaddlg.h
- workthread.h
- main.cpp
- threaddlg.cpp
- workthread.cpp
- 四、总结
前言
本章节会给大家带来Qt5 事件处理及实例——多线程及简单实例。
一、多线程及简单实例概述
通常情况下,应用程序都是在一个线程中执行操作。但是,当调用一个耗时操作(例如,大批量 I/0 或大量矩阵变换等 CPU 密集操作)时,用户界面常常会冻结。而使用多线程可解决这一问题。
多线程具有以下优势。
(1) 提高应用程序的响应速度。这对于开发图形界面的程序尤为重要,当一个操作耗时很
长时,整个系统都会等待这个操作,程序就不能响应键盘、鼠标、菜单等的操作,而使用多线程技术可将耗时长的操作置于一个新的线程,从而避免出现以上问题。
(2) 使多 CPU 系统更加有效。当线程数不大于 CPU 数目时,操作系统可以调度不同的线
程运行于不同的 CPU 上。
(3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为独立或半独立的
运行部分,这样有利于代码的理解和维护。
多线程程序具有以下特点。
(1) 多线程程序的行为无法预期,当多次执行上述程序时,每次的运行结果都可能不同。
(2) 多线程的执行顺序无法保证,它与操作系统的调度策略和线程优先级等因素有关。
(3) 多线程的切换可能发生在任何时刻、任何地点。
(4) 由于多线程对代码的敏感度高,因此对代码的细微修改都可能产生意想不到的结果。
基于以上这些特点,为了有效地使用线程,开发人员必须对其进行控制。
二、效果实例
图一
图二
三、原码实例
threaddlg.h
#ifndef THREADDLG_H
#define THREADDLG_H
#include <QDialog>
#include <QPushButton>
#include "workthread.h"
#define MAXSIZE 2
class ThreadDlg : public QDialog
{
Q_OBJECT
public:
ThreadDlg(QWidget *parent = 0);
~ThreadDlg();
private:
QPushButton *startBtn;
QPushButton *stopBtn;
QPushButton *quitBtn;
public slots:
void slotStart();
void slotStop();
private:
WorkThread *workThread[MAXSIZE];
};
#endif // THREADDLG_H
workthread.h
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
/*工作线程 WorkThread 类继承自 QThread 类*/
class WorkThread : public QThread
{
public:
WorkThread();
protected :
void run();
};
#endif // WORKTHREAD_H
main.cpp
#include "threaddlg.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ThreadDlg w;
w.show();
return a.exec();
}
threaddlg.cpp
#include "threaddlg.h"
#include <QHBoxLayout>
ThreadDlg::ThreadDlg(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr(" 线程"));
startBtn = new QPushButton(tr("开始"));
stopBtn = new QPushButton(tr(" 停止 ")) ;
quitBtn = new QPushButton(tr(" 退出")) ;
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(startBtn);
mainLayout->addWidget(stopBtn);
mainLayout->addWidget(quitBtn);
connect (startBtn, SIGNAL(clicked()), this, SLOT (slotStart ()));
connect (stopBtn, SIGNAL(clicked()), this, SLOT (slotStop ()));
connect (quitBtn, SIGNAL(clicked()) , this, SLOT (close ()));
}
ThreadDlg::~ThreadDlg()
{
}
/*这里使用两个循环,目的是使新建
的线程尽可能同时开始执行*/
void ThreadDlg::slotStart()
{
for(int i=0;i<MAXSIZE;i++)
{
/* 创建指定数目的 WorkThread 线程,并将 WorkThread实例的指针保存在指针数组 workThread 中。*/
workThread[i] =new WorkThread();
}
for(int i=0;i<MAXSIZE;i++)
{
/*调用 QThread 基类的 start()函数,此函数将启动 run()函数,从而使线程开始真正运行。*/
workThread[i] ->start();
}
startBtn->setEnabled(false);
stopBtn->setEnabled(true);
}
/*当用户单击“停止”按钮时,将调用槽函数 slotStop() */
void ThreadDlg::slotStop ()
{
for(int i=0;i<MAXSIZE;i++)
{
workThread [i]->terminate();
workThread[i]->wait();
}
startBtn->setEnabled(true);
stopBtn->setEnabled(false);
/*其中, workThread[i]->terminate() 、 workThread[i]->waitO: 调用 QThread 基类的 terminate()
*函数,依次终止保存在 workThread[]数组中的 WorkThread 类实例。但是, terminate()函数并不会
*立刻终止这个线程,该线程何时终止取决千操作系统的调度策略。因此,程序紧接着调用了
*QThread 基类的 wait() 函数,它使线程阻塞等待直到退出或超时。
*/
}
workthread.cpp
#include "workthread.h"
#include <QtDebug>
WorkThread::WorkThread()
{
}
/*run() 函数实际上是一个死循环,它不停地打印数字 0-9 。为了显示效果明显,程序将每一个数字重复打印 8 次。*/
void WorkThread::run()
{
while (true)
{
for(int n=0;n<10;n++)
qDebug()<<n<<n<<n<<n<<n<<n<<n<<n;
}
}
四、总结
Qt5 事件处理及实例——多线程及简单实例会在应用程序开发中经常用到的。