Qt多线程实现方式(1)——QThread

注:低级的多线程实现方式必要时需要解决线程同步问题。

QThread实现多线程目前有两种方式:继承QThread重新实现 virtual QThread::run()和使用

void QObject::moveToThread(QThread *thread)

1:继承QThread重新实现 virtual QThread::run()

注:该方法不被推荐使用,因为重写run()默认情况下使QThread管理的线程无法启用事件循环,即无法通过事件循环进行消息传递和事件处理和QThread应当被看做是新线程的入口,不应去改变该类的实现细节。

实现细目:

1:继承QThread:         class MyThread : public QThread { ......       }   

2:重写方法:                [virtual protected] void QThread::run()

实现过程:

启动线程:[slot] void QThread::start(QThread::Priority priority = InheritPriority)

任务实现:void QThread::run( ){                                           //MyThread管理的线程所执行的任务

                        while( ! this->isInterruptionRequested()) {        //见注1  

                                // 实现细节,必要时需要进行线程同步

                        }  //不一定是while方式执行任务和退出任务

                  }

结束线程:1:void QThread::requestInterruption( ) //请求线程中断

                  2:bool QThread::wait(unsigned long time = ULONG_MAX) //阻塞调用点,本线程等待MyThread所管理的线程退出。

                      unsigned long time = ULONG_MAX

                      默认无限等待直到MyThread所管理的线程退出,返回真。

                      设置等待毫秒数:若超时返回假,否则返回真。

注1:

                bool QThread::isInterruptionRequested() const

                当通过QThread::requestInterruption( )调用请求线程中断时,该函数会返回真,即请求中断成功,则退出相关操作。

  注2:    [slot] void QThread::terminate()

                非必要不要使用该函数,它可能会立即停止线程任务在任何执行路径上,线程可能来不及释放锁和做相关的线程清理工作。

2:使用void QObject::moveToThread(QThread *thread)

注:推荐使用该方法实现低级的多线程控制。QThread只管理线程相关的任务,不实现实际任务,实际任务由QObject子类实现。该方法不重写QThread::run(),也可以进行消息循环处理跨线程消息和事件处理。

实现细目:

1: 继承QObject :        class MyTask : public QObject{ ...... }

2: 使用QObject::moveToThread( ) : myTask::moveToThrad(new QThread(this)) //若该操作在QObject及其子类中

实现过程:

1:子类化QObject实现具体任务:

      class    MyTask : public QObject{        //伪代码

                Q_OBJECT;

       public:

                //相关构造和析构

                //......

                void stopTask1{ this->stoped1=true; }        //通过该调用退出任务1

                void stopTask2{ this->stoped2=true; }        //通过该调用退出任务2

        public slots : 

                //相关任务:

                void  task1( ){

                        while( !this->stoped1){         //不一定是while方式执行任务和退出任务

                                //相关任务

                        }

                }

                void  task2( ){

                        while( !this->stoped2){

                                //相关任务

                        }

                 }

                //......

        singles:

                //启动相关任务:

                void runTask1( );

                void runTask2( );

                //......

        private:

                bool stoped1=false;         //任务1的退出标志位

                bool stoped2=false;         //任务2的退出标志位

       }

2:实例化任务和连接相关控制:

        QThread*  myThread =new QThread();

        MyTask*    myTask=new MyTask();         //该类在移动之前不能存在在对象树上,否则不能移动到其他线程

        myTask->moveToThread(myThread);     //最好在连接之前移动对象

        connect(myThread,&QThread::started,myTask,&MyTask::runTask1); //该连接为直接连接,因为QThread::started在MyThread管理的线程触发

        connect(myTask,&MyTask::runTask1,myTask,&MyTask::task1); 

        connect(myTask,&MyTask::runTask2,myTask,&MyTask::task2);  

        connect(myThread,&QThread::finshed,myTask,&MyTask::deleteLater);

        关于信号连接及其连接方式的决议请查看文章:        QT信号槽的同步与异步执行_qt信号槽同步异步-优快云博客

        myThread->start();                       //启动线程, 开启任务1,在myThread管理的线程发出       started信号

        //或myTask->thread()->start();      

        myTask->stopTask1( );                 //停止任务1

        myTask->runTask2( );                   //开启任务2

         myTask->stopTask2( );                 //停止任务2

         myTask->thread()->quit( );            //终止myThread管理的线程事件循环,意味着将要结束该线程,finished信号将在myThread管理的线程发出

        myTask->thread()->wait( );            //阻塞本线程,等待myThread管理的线程退出

        myThread->deleteLater( );

        注:

        相关任务应当通过信号槽的方式触发,不应该直接调用。

        任务1的信号槽是直接连接的,因为QThread::started()信号,MyTask::runTask1( )信号都在myThread管理的线程触发。

        任务2的信号槽是队列连接的,因为MyTask::runTask2( )信号在myThread对象所在的线程触发,myThread对象和其管理的线程不是同一个。

        当QThread::finshed信号被发出时,事件循环已经结束,除了删除事件之外没有其他事件可处理。因此该信号可连接相关线程里的任务对象的清理工作。

        当QThread::started信号被触发时意味着相关线程要执行但是QThread::run()还未开始调用,可以通过连接该信号执行相关线程任务。该信号是私有的,可以被连接但不能被调用触发。

                                     

                                                                            注:本文为本人工作学习总结,若有错误恳请指正

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值