zoukankan      html  css  js  c++  java
  • Qt线程实现分析-moveToThread vs 继承

    最近抽空研究了下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的区别

  • 相关阅读:
    Cocos Creator 镜头跟随(cc.follow)
    Cocos Creator 虚拟摇杆
    Creator Cocos 获取舞台尺寸 (屏幕大小)
    Cocos Creator中的计时器 (setTimeOut ,setInterval,Schedule )
    Cocos Creator Touch_End的触发条件 (Mouse事件)
    Cocos Creator Spine骨骼动画 (局部换装、全局换装)
    Cocos Creator 粒子效果
    Cocos Creator 的Http和WebSocket
    Android中图表AChartEngine学习使用与例子
    Android应用加入微信分享
  • 原文地址:https://www.cnblogs.com/swarmbees/p/10862160.html
Copyright © 2011-2022 走看看