最近抽空研究了下QThread,使用起来方式多种多样,但是在使用的同时,我们也应该去了解Qt的线程它到底是怎么玩儿的。

Qt的帮助文档里讲述了2种QThread的使用方式,一种是moveToThread,另一种是继承QThread实现run方法,下面我们分别来分析下

一、moveToThread

首先我们来先分析move这种方式,他的使用可能像下面这样

class Worker : public QObject
{
public slots:
void doWork(const QString &) {
emit resultReady(result);
}
}; class Controller : public QObject
{
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
};

这是一个标准的多线程使用方式,复杂的逻辑操作我们可以放在Worker对象的槽函数中进行,因为只有槽函数是在工作线程中执行的,下面我记录了各个函数执行时所在的线程ID

由于线程ID是每次会发生编号,可能每个人测试的结果不一样

  • Worker(): 0x4c34 主线程
  • doWork(): 0x40c8 工作线程
  • handleResults(): 0x4c34 主线程
  • ~Worker(): 0x40c8 工作线程

细心的同学就会发现了,Worker对象的构造函数和析构函数不在同一个线程里边:Worker对象的事件循环已经放到子线程中了,Worker对象删除时,是工作线程通过抛出DeferredDelete事件执行的

下面结合我自己之前的一些使用理解,来分析下moveToThread是如何运作的:

假设有这么一种场景,需要把对象obj从线程A移动到线程B

首先我自己看了Qt的这个函数源码,这里把他翻译成为了白话文,我们大家可以来看下

1、一些异常判断

  1. 确认不在同一个线程里
  2. 移动的对象不能有父类
  3. 不能移动Widget窗体
  4. 支持移动一个无所属线程的对象到指定线程
  5. 对象不在C线程时,C线程不能把对象移动到B线程,只有A线程可以

2、moveToThread_helper

  1. 构造ThreadChange事件,发送给自己
  2. 迭代所有子对象,并执行moveToThread_helper方法

3、setThreadData_helper

  1. 循环遍历,把线程A中obj对象的所有事件移动到B线程中
  2. 如果移动了新事件到线程B中,则我们需要唤醒B线程,让他去派发事件
  3. 迭代所有子对象,并执行setThreadData_helper方法

二、继承QThread

假设说我们继承QThread实现了一个UsThread,使用起来可能像这样

UsThread thd;

经过我的实践,很可惜,除了run函数以外,所有的函数执行,包括对象都在主线程中

如果你想着thd.moveToThread这么干,那么可能会被打死

结论:个人推荐使用moveToThread这种方式进行子线程编写

更详细的测试结果可以参考

QThread使用——关于run和movetoThread的区别

Qt线程实现分析-moveToThread vs 继承的更多相关文章

  1. Qt线程(1) moveToThread

    若在Qt准备使用线程类一般有两种方式(1) 采用WorkObject配合QThread进行使用 (2)继承QThread, 重载run()函数即可. 注:采用Qt::Concurrent之类的不在本文 ...

  2. QT线程使用收集示例

    关于多线程问题: Qt和Boost做跨平台的线程封装,OpenMP主要做并行计算,让不精通多线程的人也能高效地利用CPU的计算能力.个人倾向于用boost.thread, boost.mpi.   一 ...

  3. Qt源码分析之QObject

    原文:http://blog.csdn.net/oowgsoo/article/details/1529284 我感觉oowgsoo兄弟写的分析相当透彻,赞! 1.试验代码: #include < ...

  4. QT源码分析(从QApplication开始)

    QT源码分析 转载自:http://no001.blog.51cto.com/1142339/282130 今天,在给同学讲东西的时候,谈到了Qt源代码的问题,才发现自己对Qt机制的了解是在太少了,而 ...

  5. Qt 线程基础(QThread、QtConcurrent、QThreadPool等)

      使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使 ...

  6. Qt线程(2) QThread中使用WorkObject

    一般继承QThread的WorkThread都会在重载的run()中创建临时的WorkObject,这样能确定这个WorkObject在该thread中使用 那如果这个WorkObject是个Sing ...

  7. QT核心编程之Qt线程 (c)

    QT核心编程之Qt线程是本节要介绍的内容,QT核心编程我们要分几个部分来介绍,想参考更多内容,请看末尾的编辑推荐进行详细阅读,先来看本篇内容. Qt对线程提供了支持,它引入了一些基本与平台无关的线程类 ...

  8. Qt 线程基础(Thread Basics的翻译,线程的五种使用情况)

    Qt 线程基础(QThread.QtConcurrent等) 转载自:http://blog.csdn.net/dbzhang800/article/details/6554104 昨晚看Qt的Man ...

  9. Qt 学习之路 :Qt 线程相关类

    希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...

随机推荐

  1. Java并发之内存模型(JMM)浅析

    背景 学习Java并发编程,JMM是绕不过的槛.在Java规范里面指出了JMM是一个比较开拓性的尝试,是一种试图定义一个一致的.跨平台的内存模型.JMM的最初目的,就是为了能够支多线程程序设计的,每个 ...

  2. 《Java 8 in Action》Chapter 1:为什么要关心Java 8

    自1998年 JDK 1.0(Java 1.0) 发布以来,Java 已经受到了学生.项目经理和程序员等一大批活跃用户的欢迎.这一语言极富活力,不断被用在大大小小的项目里.从 Java 1.1(199 ...

  3. 【Windows Of CCPC HDU - 6708】【打表,找规律】

    题意分析 HDU - 6708 题意:给出一个整数k,要求你输出一个长和宽均为2^k^ 的符合要求的矩阵.比如k等于1时输出 \[ \begin{matrix} C & C \\ P & ...

  4. Nginx总结(三)基于端口的虚拟主机配置

    前面讲了如何配置基于IP的虚拟主机,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天就 ...

  5. 从0系统学Android-2.5更多隐式Intent用法

    本系列文章,参考<第一行代码>,作为个人笔记 更多内容:更多精品文章分类 从0系统学Android-2.5更多隐式Intent用法 上一节中我们学习了通过隐式 Intent 来启动 Act ...

  6. 第五章 Spring核心概念

     5.1.1 企业级应用开发    企业级应用是指那些为商业组织,大型企业而创建部署的解决方案及应用,大型企业级应用的结构复杂,涉及的外部资源众多,事务密集,数据规模大,用户数量多,有较强的安全性考虑 ...

  7. 【sybase】You can’t run SELECT INTO in this database的解决办法

    进入master 数据库,使用sp_dboption test ,'select into',true命令(其中test为要设置可用的数据库)

  8. Redis主从复制的原理

    更多内容,欢迎关注微信公众号:全菜工程师小辉.公众号回复关键词,领取免费学习资料. 在Redis集群中,让若干个Redis服务器去复制另一个Redis服务器,我们定义被复制的服务器为主服务器(mast ...

  9. 最短路 dijkstra+优先队列+邻接表

    http://acm.hdu.edu.cn/showproblem.php?pid=2544 #include<iostream> #include<queue> #inclu ...

  10. codeforces C. Sonya and Problem Wihtout a Legend(dp or 思维)

    题目链接:http://codeforces.com/contest/713/problem/C 题解:这题也算是挺经典的题目了,这里附上3种解法优化程度层层递进,还有这里a[i]-i<=a[i ...