zoukankan      html  css  js  c++  java
  • 总结使用QObject实现线程

    补充一下为什么需要使用继承QObject来实现线程:

    原因就是使用继承QThread的类只有run函数是属于新线程的,而其他非run函数依旧属于旧的线程。如果QThread是在ui所在的线程里生成,那么QThread的其他非run函数都是和ui线程一样的,所以,QThread的继承类的其他函数尽量别要有太耗时的操作,要确保所有耗时的操作都在run函数里。在UI线程下调用QThread的非run函数(其实也不应该直接调用run函数,而应该使用start函数),和执行普通函数无区别,这时,如果这个函数要对QThread的某个变量进行变更,而这个变量在run函数里也会被用到,这时就需要注意加锁的问题,因为可能这个变量前几毫秒刚刚在run中调用,再调用时已经被另外的线程修改了。

    话不多说,直接上代码,里边有我的注释:

    //main.cpp
    
    #include <QtCore/QCoreApplication>
    #include "Controller.h"
    
    /*
    使用QObject创建线程总结:
    1、随便写一个类继承自QObject
    2、定义一个工作函数,将耗时的过程写在里边
    3、写一个线程管理类,该类至少包含一个QThread和一个你自定义的工作类成员变量
    4、在管理类的构造函数中将自定义工作类的对象使用moveToThread()函数移动到QThread对象中,此时该对象的所有东西都是线程对象的了
    5、没必要重写run函数,只要在控制类中自定义一个工作信号,并将该工作信号于你自定义的工作函数连接起来,每当发出工作信号,工作函数就开始执行
    6、必须在发出工作信号之前执行线程对象的start()函数,否则工作函数无法执行
    7、当工作函数中存在while循环时,如果你想手动终止线程中的while循环,那么一定不能使用属于线程的槽函数,因为此时消息队列被线程中的while‘饿死’了。
    */
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        Controller control;
        control.Start();
    
        return a.exec();
    }
    //cyx_Worker.h
    
    #pragma once
    #include <QObject>
    #include <QMutex>
    
    class cyx_Worker :public QObject {
        Q_OBJECT
    public:
        cyx_Worker(QObject* parent = 0);
        ~cyx_Worker();
        void Stop();
    
    public slots:
        virtual void slot_doWork();
    
    private:
        bool m_bstop;
        QMutex m_mutex;
    };
    //cyx_Worker.cpp
    
    #include "cyx_Worker.h"
    #include <QDateTime>
    #include <QMutexLocker>
    #include <iostream>
    using namespace std;
    
    cyx_Worker::cyx_Worker(QObject* parent /* = 0 */) :QObject(parent) {
        m_bstop = false;
    }
    
    cyx_Worker::~cyx_Worker(){}
    
    void cyx_Worker::slot_doWork() {
        qint64 currenttime = QDateTime::currentMSecsSinceEpoch();
        int count = 0;
        {
            QMutexLocker locker(&m_mutex);
            m_bstop = false;
        }
        while (!m_bstop) {
            if (QDateTime::currentMSecsSinceEpoch() - currenttime >= 2000) {
                currenttime = QDateTime::currentMSecsSinceEpoch();
                cout << count << endl;
                count++;
            }
        }
    }
    
    void cyx_Worker::Stop() {
        cout << "stop!" << endl;
        QMutexLocker locker(&m_mutex);
        m_bstop = true;
    }
    //Controller.h
    
    #pragma once
    #include <QThread>
    #include <QTimer>
    #include "cyx_Worker.h"
    
    class Controller :public QObject {
        Q_OBJECT
    public:
        Controller(QObject* parent = 0);
        ~Controller();
        void Start();
    
    signals:
        void sig_stop();
        void sig_doWork();
    
    public slots:
        void slot_stop();
    
    private:
        QThread m_workthread;
        QTimer* timer;
        cyx_Worker* m_worker;
    };
    //Controller.cpp
    
    #include "Controller.h"
    #include <iostream>
    using namespace std;
    
    Controller::Controller(QObject* parent /* = 0 */) :QObject(parent) {
        m_worker = new cyx_Worker;
        timer = new QTimer;
        m_worker->moveToThread(&m_workthread);
        connect(timer, SIGNAL(timeout()), this, SIGNAL(sig_stop()));
        connect(&m_workthread, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
        connect(this, SIGNAL(sig_doWork()), m_worker, SLOT(slot_doWork()));
        connect(this, SIGNAL(sig_stop()), this, SLOT(slot_stop()));
    }
    
    Controller::~Controller() {
        m_workthread.quit();
        m_workthread.wait();        //m_workthread并没有new出来,所以使用wait等待线程执行结束,如果使用new,则需绑定deleteLater让线程自杀
    }
    
    void Controller::Start() {
        timer->setSingleShot(true);
        timer->start(10000);
        m_workthread.start();
        emit sig_doWork();
    }
    
    void Controller::slot_stop() {
        m_worker->Stop();
    }
    温润如玉,坚毅如铁。
  • 相关阅读:
    redis qps监控
    不要对md5file.read()计算md5值
    Kubernetes-基于helm安装部署高可用的Redis及其形态探索(二)
    Kubernetes-基于helm安装部署高可用的Redis及其形态探索
    mongodb replication set 主从切换
    使用packstack安装pike版本的openstack
    redis性能测试方法
    mysql与mariadb性能测试方法
    Mongodb集群形式探究-一主一从一仲裁。
    Python元类
  • 原文地址:https://www.cnblogs.com/heisen/p/10561335.html
Copyright © 2011-2022 走看看