QThread类提供了与系统无关的线程。
QThread代表在程序中一个单独的线程控制。线程在run()中开始执行,默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的事件循环。
当线程started()和finished()时,QThread会通过一个信号通知你,可以使用isFinished()和isRunning()来查询线程的状态。
你可以通过调用exit()或quit()来停止线程。在极端情况下,可能要强行terminate()一个执行线程。但是,这样做很危险,下面会详细说明。
从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::deleteLater()槽。
使用wait()来阻塞调用的线程,直到其它线程执行完毕(或者直到指定的时间过去)。
QThread还提供了静态的、平台独立的休眠函数:sleep()、msleep()、usleep(),允许秒,毫秒和微秒来区分,这些函数在Qt5.0中被设为public。
注意:
一般情况下,wait()和sleep()函数应该不需要,因为Qt是一个事件驱动型框架。考虑监听finished()信号来取代wait(),使用QTimer来取代sleep()。
静态函数currentThreadId()和currentThread()返回标识当前正在执行的线程。前者返回该线程平台特定的ID,后者返回一个线程指针。
要设置线程的名称,可以在启动线程之前调用setObjectName()。如果不调用setObjectName(),线程的名称将是线程对象的运行时类型(QThread子类的类名)。
可以将常用的接口按照功能进行以下分类
void start(Priority priority = InheritPriority)[slot]
调用后会执行run()函数,但在run()函数执行前会发射信号started(),操作系统将根据优先级参数调度线程。如果线程已经在运行,那么这个函数什么也不做。优先级参数的效果取决于操作系统的调度策略
设置正在运行线程的优先级。如果线程没有运行,此函数不执行任何操作并立即返回。使用的start()来启动一个线程具有特定的优先级。优先级参数可以是QThread::Priority枚举除InheritPriortyd的任何值。
枚举QThread::Priority:
|
常量
|
值
|
描述
|
|
QThread::IdlePriority
|
0
|
没有其它线程运行时才调度
|
|
QThread::LowestPriority
|
1
|
比LowPriority调度频率低
|
|
QThread::LowPriority
|
2
|
比NormalPriority调度频率低
|
|
QThread::NormalPriority
|
3
|
操作系统的默认优先级
|
|
QThread::HighPriority
|
4
|
比NormalPriority调度频繁
|
|
QThread::HighestPriority
|
5
|
比HighPriority调度频繁
|
|
QThread::TimeCriticalPriority
|
6
|
尽可能频繁的调度
|
|
QThread::InheritPriority
|
7
|
使用和创建线程同样的优先级. 这是默认值
|
子类化QThread
class WorkerThread : public QThread
Q_OBJECT
void run() Q_DECL_OVERRIDE {
QString result;
// 这里是耗时或阻塞的操作
emit resultReady(result);
signals:
void resultReady(const QString &s);
void MyObject::startWorkInAThread()
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
上面的示例,在run()函数返回后线程就会退出,在线程中将不会有任何的事件循环运行,除非调用exec()。
重要的是要记住,一个线程实例位于实例化它的旧线程中,而非调用run()的新线程中,这意味着所有线程的queued slots将在旧线程中执行。
采取合理的措施来优雅地结束线程,一般思路:
- 发起线程退出操作,调用quit()或exit()。
- 等待线程完全停止,删除创建在堆上的对象。
- 适当的使用wait()(用于等待线程的退出)和合理的算法。
#include <QThread>
#include <QMutexLocker>
class WorkerThread : public QThread
Q_OBJECT
public:
explicit WorkerThread(QObject *parent = 0)
: QThread(parent),
m_bStopped(false)
qDebug() << "Worker Thread : " << QThread::currentThreadId();
~WorkerThread()
quit();
wait();
void stop()
qDebug() << "Worker Stop Thread : " << QThread::currentThreadId();
QMutexLocker locker(&m_mutex);
m_bStopped = true;
protected:
virtual void run() Q_DECL_OVERRIDE {
qDebug() << "Worker Run Thread : " << QThread::currentThreadId();
int nValue = 0;
while (nValue < 100)
// 休眠50毫秒
msleep(50);
++nValue;
// 准备更新
emit resultReady(nValue);
// 检测是否停止
QMutexLocker locker(&m_mutex);
if (m_bStopped)
break;
// locker超出范围并释放互斥锁
signals:
void resultReady(int value);
private:
bool m_bStopped;
QMutex m_mutex;
当主线程调用stop()更新m_bStopped的时候,run()函数也极有可能正在访问它(这时,他们处于不同的线程),所以存在资源竞争,因此需要加锁,保证共享数据的安全性。
主线程会调用
deleteLater,然后自动调用析构函数!
在程序中使用线程可以提高程序的性能、并发性、响应性和稳定性,使得程序设计更加灵活和简单。但是,线程编程也有一些挑战,如线程安全性和死锁等问题需要格外注意。我们使用QT框架编程时,可以用框架提供的线程类QThread来管理线程。本文将介绍使用QThread编程时的两种方式,并给出一个数据同步的示例。在介绍QThread之前先复习下线程的定义,线程是操作系统中的基本执行单元,是一个独立的执行路径。每个线程都有自己的栈空间,用于存储本地变量和函数调用的上下文。
Qt中,开启子线程,一般有两种方法:
a, 定义工作类worker:
worker继承 QThread, 重写run函数,在主线程中实例化worker,把耗时工作放进worker的run函数中完成,结束后,往主线程中发信号,传递参数即可。
注意:此worker的实例,只有run函数在子线程中执行,worker的其他函数,均在主线程中执行。
b, 定义工作类worker:
worker...
一:Qt的线程优先级
QThread::IdlePriority 0 scheduled only when no other threads are running.
QThread::LowestPriority 1 scheduled less often than LowPriority.
QThread::LowPriority 2 scheduled less often than Normal
QThread类提供了一个与平台无关的管理线程的方法。一个QThread对象管理一个线程。QThread的执行从run()函数的执行开始,在Qt自带的QThread类中,run()函数通过调用exec()函数来启动事件循环机制,并且在线程内部处理Qt的事件。在Qt中建立线程的主要目的就是为了用线程来处理那些耗时的后台操作,从而让主界面能及时响应用户的请求操作。QThread的使用方法有如下两种:下面通过具体的方法描述和例子来介绍两种方法。 首先新建一个worker类,该类重点在于其doWork槽
文章目录Qt 线程中QThread的使用1. 线程类 QThread1.1 常用共用成员函数1.2 信号槽1.3 静态函数1.4 任务处理函数2. 使用方式 12.2 示例代码3. 使用方式 23.1 操作步骤3.2 示例代码
Qt 线程中QThread的使用
在进行桌面应用程序开发的时候, 假设应用程序在某些情况下需要处理比较复杂的逻辑, 如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不仅可以
我们继承QThread,重写run();
第一反应是不是应该添加个标志,在run()中判断暂停状态。嗯,没错,不过我们不能用普通变量,否则有线程非安全风险。这里使用C++提供的原子类型std::atomic_bool。
线程暂停期间,不能空跑消耗cpu,故我们使用Qt条件变量QWaitCondition,配合QMutex。
大概就是这么点内容吧,实现代码如下:
Thread.h
#include <
注意:定义的信号有一个参数,类型是字符串str。将获得的新闻标题呈现在列表中,并调整进度条的数值。到此为止,我们已经完成所有工作:从新闻网站获取新闻的线程线程与主线程的连接如何实现自定义信号如何使用内建信号。
为了创建新的线程执行相应处理,继承 QThread 并且重新实现 run()
实例化创建的线程子类,并调用 start()
想要设置线程优先级,通过设置 start()函数的priority 参数, 或者thread.setPriority(),默认继承所在线程的优先级。
多线程与多进程是现代操作系统中非常重要的两个概念,多进程强调分工,多线程强调合作,本文只谈多线程。
多线程有硬件多线程和软件多线程之分,下面只谈软件多线程。
多线程的能力一般是由操作系统(如Windows、Linux)提供,不同的操作系统在多线程的实现上是不同的,而且呈现出来的接口也是不统一的。很多程序开发框架都提供了独立于操作系统平台的多线程接口。
Qt的QThread提供了一个独立于平台的方法管理多线程。一个QThread对象管理着一个线程。QThread通过执行run()开始。默认情况下,run
有时候写代码时总是忘记delete一些自己new的对象,每次都是在整个类写完之后对整个类的资源做回收。也是相当于检查一遍,避免一些未被处理资源。
而这两天在检查的时候,发现了一个比较好的写法,obj->deleteLater();这种写法,按照字面意思理解,就是对象延迟析构。
go语言中有一个延迟执行的语句,非常好用,比如:
filePath := "e:/code/golang.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREA
该函数是QObject类的函数:
deletelater的原理是 QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。
所有继承自QObejet类的类都会维护一个自己的子对象列表,同时会存储自己的父对象,所以界面中的各个控件(各个控价的基类都是QObject)可以实现层次!
“当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的
夫唯不争,故天下莫能与之争 -- 老子
在C++中,delete 和 new 必须 配对使用,Qt作为C++的库,显然是不会违背C++原则。但是,qt有自己的内存管理,有时候虽然使用了new,却可以不用使用delete。
Qt半自动的内存管理:
在Qt中,以下情况下你...