精华内容
下载资源
问答
  • QThread的用法

    2019-06-22 13:50:20
  • QThread的用法:开启与退出 转载于:https://www.cnblogs.com/zhehan54/p/9014396.html

     

    QThread的用法:开启与退出

     

    转载于:https://www.cnblogs.com/zhehan54/p/9014396.html

    展开全文
  • 这次打算记录些东西,就先说说QThread的使用吧。 环境:VS2015 + Qt 5.12.5(应该只要是Qt5都可以) QThread有两种用法: 1、写一个QObject子类,实例化之后,用moveToThread()将它移到新线程中,然后运行线程...

    写技术文章好像还是好多年前的事了,记得那时候刚接触C#的时候写过几篇,之后就一直没有写过了,因为习惯性了用文件记录,然后放到网盘,需要时从网盘找。可能是因为文笔不好,反正就那么回事了。这次打算记录些东西,就先说说QThread的使用吧。

    环境:VS2015 + Qt 5.12.5(应该只要是Qt5都可以)

    QThread有两种用法:

    1、写一个QObject子类,实例化之后,用moveToThread()将它移到新线程中,然后运行线程(推荐)

    2、子类化一个QThread,然后实现run()虚函数

    要用好QThread,首先要认识到QThread实际上只是一个线程管理的类,它并不是线程本身,所以它在创建它的线程空间里。下面分别看两个用法的示例。

    用法1示例:

    #include <QCoreApplication>
    #include <QObject>
    #include <QThread>
    
    //为了直观就将代码和头文件放一起了
    
    class ChildObj : public QObject
    {
    	Q_OBJECT
    public:
    	ChildObj(int value, QObject *parent = nullptr) : QObject(parent), mValue(value) {}
        int Value(void) const { return mValue; }
    	
    private:
    	int mValue;
    };
    
    class ParentObj : public QObject
    {
    	Q_OBJECT
    public:
    	ParentObj(QObject *parent) : QObject(parent), 
    		mChildA(10),       //没有指定父对象,所以它属于调用这个方法时所在的线程(本例在主线程调用该方法,所以它属于主线程)
    		mChildB(11, this), //指定父对象为this(即:parentObj),而parentObj被移入子线程,所以它属于子线程
    		mChildC(new ChildObj(12)),       //没有指定父对象,所以它属于调用这个方法时所在的线程(本例在主线程调用该方法,所以它属于主线程)
    		mChildD(new ChildObj(13, this)), //指定父对象为this(即:parentObj),而parentObj被移入子线程,所以它属于子线程
    		mChildE(nullptr),
    		mChildF(nullptr)
    	{
    		mChildE = new ChildObj(14);       //没有指定父对象,所以它属于调用这个方法时所在的线程(本例在主线程调用该方法,所以它属于主线程)
    		mChildF = new ChildObj(15, this); //指定父对象为this(即:parentObj),而parentObj被移入子线程,所以它属于子线程
    	}
        ~ParentObj()
        {
            //如果线程正在运行,则退出,并等待完成退出
            if(isRunning()) 
            {
                mStopFlag = true;
                while(isRunning()) QThread::usleep(5);
            }
        }
    	
        void PrintMsg(void) { emit SigPrintMsg("This is a test"); }
        void Stop(void) { mStopFlag = true; }
    	void CreateChildI(void) { mChildI = new ChildObj(18); }
    	void CreateChildJ(void) { mChildJ = new ChildObj(19, this); }
    	
    	void Run()
    	{
    		mChildG = new ChildObj(16);       //没有指定父对象,所以它属于调用这个方法时所在的线程(这个方法在子线程中运行,所以它属于子线程)
    		mChildH = new ChildObj(17, this); //指定父对象为this(即:parentObj),而parentObj被移入子线程,所以它属于子线程
    
            mStopFlag = false;
            while(!mStopFlag)
            {
                //在这里做一些想要做的事
            }
            emit SigFinished();
    	}
    
    signals:
        void SigFinished(void);
        void SigPrintMsg(const QString &msg);
    	
    private:
        bool mStopFlag;//是否退出标志
    	ChildObj mChildA;	//本示例结果:主线程
    	ChildObj mChildB;	//本示例结果:子线程
    	ChildObj *mChildC;	//本示例结果:主线程
    	ChildObj *mChildD;	//本示例结果:子线程
    	ChildObj *mChildE;	//本示例结果:主线程
    	ChildObj *mChildF;	//本示例结果:子线程
    	ChildObj *mChildG;	//本示例结果:子线程
    	ChildObj *mChildH;	//本示例结果:子线程
    	ChildObj *mChildI;	//本示例结果:主线程
    	ChildObj *mChildJ;	//本示例结果:主线程
    };
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication a(argc, argv);
    
        ParentObj *parentObj = new ParentObj;
    	QThread *thread = new QThread;
    	parentObj->moveToThread(&thread);//将parentObj移到子线程thread中
    
        //连接信号和槽
    	connect(thread, &QThread::started, parentObj, &ParentObj::Run);//线程启动后自动执行ParentObj::Run()
        //在使用过程中发现过一些奇怪的情况:
        //使用connect(thread, &QThread::finished, thread, &QThread::deleteLater);有时候不会触发QThread::deleteLater
        //使用connect(thread, &QThread::finished, [=]{thread.deleteLater();});每次都可以触发QThread::deleteLater
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);//线程退出后自动删除线程对象
        connect(parentObj, &ParentObj::SigFinished, [=]{ delete parentObj; thread->quit(); });//通知其它模块退出线程
        connect(parentObj, &ParentObj::SigPrintMsg, [=](const QString &msg){ qDebug("%s", msg.toStdString().c_str());});//打印出信息
    
    	thread->start();//必须运行线程,不运行的话本例中的ParentObj::Run()是不会执行的
        //本例中,执行thread->start()之后会调用ParentObj::Run()
        //但ParentObj::Run()如果很快就退出了
        //此时再通过其它线程调用parentObj->PrintMsg(),则:
        //connect(parentObj, &ParentObj::SigPrintMsg, [=](const QString &msg){ qDebug("%s", msg.toStdString().c_str());});这句不会被触发
        //因为这个时候parentObj已经被移到thread中了,而thread线程已经退出了,无法再发出SigPrintMsg了
    	
        //主线程还是可以调用这些方法的
    	parentObj->CreateChildI(); //由主线程调用此方法,所以parentObj->mChildI在主线程
    	parentObj->CreateChildJ(); //由主线程调用此方法,但parentObj在子线程,所以它在主线程还是子线程?实测结果:主线程
    
        QThread::usleep(5000);//延时几秒钟
        thread->Stop();//退出线程
        while(thread->isRunning()) QThread::usleep(10); //等待线程退出
    
        //事件循环
        return a.exec();
    }

    使用时需要注意:调用类里面的某个方法时控制权在哪个线程,则那个方法就是在哪个线程中执行,所以,如果子线程和主线程都要用到该对象,就需要使用锁!例如上例中的parentObj->CreateChildI()在主线程中执行;因为parentObj已经移动到子线程中,而且子线程已运行,所以ParentObj::Run()在子线程中执行。

    另外,有些Qt对象(例如:QSerialPort、QTcpSocket、QUdpSocket)如果它存在的线程不处理好,会出现问题(这时候,在构造函数中初始化这类对象时要指定它的父对象为this!)

     

    用法2示例:

    #include <QCoreApplication>
    #include <QObject>
    #include <QThread>
    
    //为了直观就将代码和头文件放一起了
    
    class ChildThread : public QThread
    {
    	Q_OBJECT
    public:
    	ChildThread (QThread *parent = nullptr) : QThread(parent), 
            mValue_1(1),       // mValue_1在主线程空间
            mValue_2(new int), // mValue_1在主线程空间
            mValue_3(nullptr)
        { }
        ~ChildThread() 
        { 
            //如果线程正在运行,则退出,并等待完成退出
            if(isRunning()) 
            {
                mStopFlag = true;
                while(isRunning()) QThread::usleep(5);
            }
        }
    	
        void Stop(void) { mStopFlag = true; }
    	
    	void Run()
    	{
            mValue_3 = new int;//mValue_3在子线程空间
            mStopFlag = false;
            while(!mStopFlag)
            {
                //在这里做一些想要做的事
            }
            emit SigFinished();
    	}
    
    signals:
        void SigFinished(void);
    	
    private:
        bool mStopFlag;//是否退出标志
        int mValue_1;
        int *mValue_2;
        int *mValue_3;
    };
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication a(argc, argv);
    
        ChildThread *thread = new ChildThread;
        connect(thread, &ChildThread::SigFinished, thread, QThread::deleteLater);//自动释放
    	thread->start();//必须运行线程,不运行的话本例中的ChildThread::Run()是不会执行的
    
        QThread::usleep(5000);//延时几秒钟
        thread->Stop();//退出线程
        while(thread->isRunning()) QThread::usleep(10); //等待线程退出
    
        //事件循环
        return a.exec();
    }

    总的来说,这种用法只有run()才是在子线程中(即:在run()中创建的变量和指针才在子线程),其它都在主线程!

     

    展开全文
  • # 22-QThread的用法

    2020-01-07 15:35:52
    一、继承QThread实现多线程 #ifndef WORKER_H #define WORKER_H #include <QThread> #include <QDebug> class Worker : public QThread { Q_OBJECT public: Worker(); signals: ...

    一、继承QThread实现多线程

    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QThread>
    #include <QDebug>
    
    class Worker : public QThread
    {
        Q_OBJECT
    public:
        Worker();
    
    signals:
        void Finished(int value);
    
    private:
        void run() override;
    };
    
    #endif // WORKER_H
    
    
    #include "worker.h"
    
    Worker::Worker()
    {
        qDebug() << "Worker::Worker() Thread ID = " << QThread::currentThreadId();
    }
    
    void Worker::run() {
    
        qDebug() << "Worker::run() Thread ID = " << QThread::currentThreadId();
    
        for (int a = 1000; a > 0; a --) {
            for (int b = 1000; b > 0; b --) {
    
            }
        }
        emit Finished(3);
    }
    
    
    #ifndef CONTROLLER_H
    #define CONTROLLER_H
    
    #include <QObject>
    #include <QDebug>
    #include "worker.h"
    
    class Controller : public QObject
    {
        Q_OBJECT
    public:
        Controller();
        ~Controller();
    
        void StartProcess();
    
    private slots:
        void Result(int value);
    
    private:
        Worker *worker_p;
    };
    
    #endif // CONTROLLER_H
    
    
    #include "controller.h"
    
    Controller::Controller()
    {
        worker_p = new Worker();
        connect(worker_p, &Worker::Finished, this, &Controller::Result);
    }
    
    Controller::~Controller() {
        delete worker_p;
    }
    
    void Controller::StartProcess() {
        qDebug() << "Controller::StartProcess() thread ID = " << QThread::currentThreadId();
        worker_p->start();
    }
    
    void Controller::Result(int value) {
        qDebug() << "Controller::Result  = " << value << " thread Id = " << QThread::currentThreadId();
    }
    
    
    #include <QCoreApplication>
    #include <QDebug>
    #include "controller.h"
    
    int main(int argc, char *argv[])
    {
        qDebug()<<"Main Thread ID = "<<QThread::currentThreadId();
        QCoreApplication a(argc, argv);
        Controller c;
        c.StartProcess();
        return a.exec();
    }
    
    

    二、QObject::moveToThread()实现多线程

    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QObject>
    #include <QDebug>
    #include <QThread>
    
    class Worker : public QObject
    {
        Q_OBJECT
    public:
        Worker();
    
    signals:
        void Finished(int value);
    
    public:
        void DoWork();
    };
    
    #endif // WORKER_H
    
    
    #include "worker.h"
    
    Worker::Worker()
    {
        qDebug() << "Worker::Worker() Thread ID = " << QThread::currentThreadId();
    }
    
    void Worker::DoWork() {
        qDebug() << "Worker::DoWork Thread ID = " << QThread::currentThreadId();
    
        for (int a = 1000; a > 0; a --) {
            for (int b = 1000; b > 0; b --) {
    
            }
        }
    
        emit Finished(3);
    }
    
    
    
    #ifndef CONTROLLER_H
    #define CONTROLLER_H
    
    #include <QObject>
    #include <QThread>
    #include <QDebug>
    
    #include "worker.h"
    
    class Controller : public QObject
    {
        Q_OBJECT
    public:
        Controller();
        ~Controller();
    
        void StartProcess();
    
    private slots:
        void Result(int value);
    
    private:
        QThread *thread_p;
    };
    
    #endif // CONTROLLER_H
    
    
    #include "controller.h"
    
    Controller::Controller()
    {
        thread_p = new QThread();
        Worker *worker = new Worker();
        worker->moveToThread(thread_p);
        connect(worker, &Worker::Finished, this, &Controller::Result);
    
        connect(thread_p, &QThread::started, worker, &Worker::DoWork);
        connect(thread_p, &QThread::finished, worker, &QObject::deleteLater);
    }
    
    Controller::~Controller()
    {
        thread_p->quit();
        thread_p->wait();
        delete thread_p;
    }
    
    void Controller::StartProcess() {
        qDebug() << "Controller::StartProcess() thread ID = " << QThread::currentThreadId();
        thread_p->start();
    }
    
    void Controller::Result(int value) {
        qDebug() << "Controller::Result  = " << value << " thread Id = " << QThread::currentThreadId();
    }
    
    
    #include <QCoreApplication>
    #include <QDebug>
    #include "controller.h"
    
    int main(int argc, char *argv[])
    {
        qDebug()<<"Main Thread ID = "<<QThread::currentThreadId();
        QCoreApplication a(argc, argv);
        Controller c;
        c.StartProcess();
        return a.exec();
    }
    
    
    展开全文
  • QThread的用法! 分类:QT-trolltech2007-08-01 15:17 #include &lt;qthread.h&gt; class MyThread : public QThread { public: virtual void run(); }; void MyThread::run() { for( int count...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 193
精华内容 77
关键字:

qthread的用法