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(),操作系统将根据优先级参数调度线程。如果线程已经在运行,那么这个函数什么也不做。优先级参数的效果取决于操作系统的调度策略
线程执行
int exec() [protected]
进入事件循环并等待直到调用exit(),返回值是通过调用exit()来获得,如果调用成功则范围0。
void run() [virtual protected]
线程的起点,在调用start()之后,新创建的线程就会调用这个函数,默认实现调用exec(),大多数需要重新实现这个函数,便于管理自己的线程。该方法返回时,该线程的执行将结束。
线程退出
void quit() [slot]
告诉线程事件循环退出,返回0表示成功,相当于调用了QThread::exit(0)。
void exit(int returnCode = 0)
告诉线程事件循环退出。调用这个函数后,线程离开事件循环后返回,QEventLoop::exec()返回returnCode,按照惯例,0表示成功;任何非0值表示失败。
void requestInterruption()
请求线程的中断。该请求是咨询意见并且取决于线程上运行的代码,来决定是否及如何执行这样的请求。此函数不停止线程上运行的任何事件循环,并且在任何情况下都不会终止它。
线程等待
void msleep(unsigned long msecs) [static]
强制当前线程睡眠msecs毫秒
void sleep(unsigned long secs) [static]
强制当前线程睡眠secs秒
void usleep(unsigned long usecs) [static]
强制当前线程睡眠usecs微秒
bool wait(unsigned long time = ULONG_MAX)
线程将会被阻塞,等待time毫秒。和sleep不同的是,如果线程退出,wait会返回。
线程状态
bool isFinished() const
线程是否结束
bool isRunning() const
线程是否正在运行
线程优先级
void setPriority(Priority priority)
设置正在运行线程的优先级。如果线程没有运行,此函数不执行任何操作并立即返回。使用的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_OBJECTvoid 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将在旧线程中执行。
采取合理的措施来优雅地结束线程,一般思路:
  1. 发起线程退出操作,调用quit()或exit()。
  2. 等待线程完全停止,删除创建在堆上的对象。
  3. 适当的使用wait()(用于等待线程的退出)和合理的算法。
#include <QThread>
#include <QMutexLocker>class WorkerThread : public QThread
{Q_OBJECTpublic: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用法相关推荐

  1. Qt多线程-QThread

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThread     本文地址:http://techieliang.com/2 ...

  2. Qt QPushButton按钮用法详解

    Qt QPushButton按钮用法详解 按钮是 GUI 开发中最常用到的一种控件,作为一款著名的 GUI 开发框架,Qt 提供了很多种按钮,比如 QPushButton(普通按钮).QRadioBu ...

  3. Qt IFW基本用法

    概述 在上一篇文章中简单介绍了Qt IFW的优势,并且介绍了如何下载安装软件,那么,在本篇中来看一下如何使用IFW创建一个最简单的应用安装包,并介绍一些基本用法. 运行示例 在介绍之前我们首先跑一个Q ...

  4. Qt之QTemporaryDir用法(创建临时目录)

    概述 在 Qt 开发中,有时候会要创建一个临时目录,用于存储一些临时文件,在用完过后又要删除该目录,这个逻辑自己实现起来并不复杂,多写几行代码就搞定了,但是这里要说的是更简单的用法QTemporary ...

  5. QT的QThread类的使用

    详细说明 QThread类提供了一种独立于平台的方式来管理线程. 一个QThread对象管理程序中的一个控制线程. QThreads开始在run()中执行. 默认情况下,run()通过调用exec() ...

  6. Qt的QThread多线程使用

    QThread简介 最近开发某C++的AI项目,需要用到界面,为了计算过程不阻塞界面,需要使用多线程,在这里学习下Qt自带的多线程操作. QThread是一个与平台无关的线程类,用于多线程的编程.具体 ...

  7. QT之QPainter用法

    QPainter可以绘制从简单的直线到像饼图和弦这样的复杂形状.它也可以绘制排列的文本和像素映射.通常,它在一个"自然的"坐标系统中绘制. QPainter 一般在部件的绘图事件 ...

  8. qt: exec()的用法,accept()和accepted的概念

    转载:http://blog.csdn.net/xdlichen/article/details/46374517 本篇,会重点讲述模式对话框,以及exec()的用法,accept()和accepte ...

  9. QT QTableWidget的用法

    简述: 表格类是Qt中常用的控件,如QTableWidget,QTableView.QTableWidget是QTableView的子类,主要区别是QTableView可以使用自定义的数据模型来显示内 ...

最新文章

  1. 如何将txt格式的数据导入到MATLAB中,并绘制图线
  2. ubuntu16.04将普通用户提升至root权限
  3. jQuery获取所有父级元素及同级元素及子元素的方法
  4. elementui下拉框 清空_巧妙解决element-ui下拉框选项过多的问题
  5. Python - Excel文件与CSV文件相互转化
  6. Python subprocess命令行中文乱码
  7. 用Javascript滚动到页面底部,并能正确判断出页面已到底部的方法
  8. BIND DNS 软件修复高危 DoS 漏洞
  9. cv::cornerSubPix()亚像素角点检测
  10. ubuntu16.04 kinect2 驱动和ROS驱动
  11. Linux中安装软件
  12. 社交网络影响力最大化基础知识总结
  13. 软件测试中的测试文档
  14. 全裸或半裸的大肚照国际接轨 细数女星大尺度斗艳孕照
  15. C#篇-值类型和引用类型
  16. postgres汉字转换为拼音
  17. 经典面试题【老鼠喝水】
  18. 关于电脑网络显示红叉的解决方法
  19. halcon机器视觉之玩转车牌识别-超人视觉罗超
  20. 基于公共知识和一次学习的多任务流量分类

热门文章

  1. pcb钻孔披锋改善报告_高速高频PCB技术 || 玻纤效应对高速信号的影响
  2. php168为什么抛弃重新开发x1,在今天518这个特别的日子里,我们经过将近一年来,日以继夜努力研发出的X1正式对外公开发布!...
  3. java.io下载_java io 文件下载
  4. 北京大学药学院张亮仁教授/刘振明研究员课题组博士后招聘启事
  5. Cell | 大规模多组织转录组学研究揭示长非编码RNA与人类复杂疾病的联系
  6. 图像处理包magick - R版的PS - 学习笔记
  7. 种草!这只鹅虽然没有什么用,但是好可爱呀!
  8. 1.5编程基础之循环控制_41数字统计
  9. 如何修改网页中的文本内容改成自己希望的数值?
  10. c语言中行号大小调整,给自己的程序加上行号