Qt基础开发之Qt多线程类QThread与Qt定时器类QTimer的详细方法与实例分享!

Qt多线程

我们之前的程序都是单线程运行,接下来我们开始引入多线程。就相当于以前的一个人在工作,现在多个人一起工作。

Qt中非常有必要使用多线程,这是因为,Qt应用是事件驱动型的,一旦某个事件处理函数处理时间过久,就会造成其它的事件得不到及时处理。

Qt中使用QThread来管理线程,一个QThread对象,就是一个线程。QThread对象也有消息循序exec()函数,用来处理自己这个线程的事件。

Qt实现多线程有两种方式

​1、Qt第一种创建线程方式

首先要继承QThread

重写虚函数QThread::run

  [virtual protected] void QThread::run()   /*   * 基类QThread的run函数只是简单启动exec()消息循环   */

例如:

  #include <QApplication>  #include <QThread>  #include <QDebug>  class MyThread : public QThread  {  public:   void run()   {    qDebug() << "QThread begin" << endl;    qDebug() << "child thread" << QThread::currentThreadId() << endl;    QThread::sleep(5);    qDebug() << "QThread end" << endl;    exec();   }  };  ​  int main(int argc, char** argv)  {   QApplication app(argc, argv);  ​   MyThread thread;   thread.start();   qDebug() << "main thread" << QThread::currentThreadId() << endl;   QThread::sleep(5);   qDebug() << "main thread" << QThread::currentThreadId() << endl;   thread.quit();   qDebug() << "main thread thread.quit()" << endl;   tread.wait();   qDebug() << "main thread thread.wait()" << endl;   return app.exec();  }

使用QThread的quit可以退出线程的消息循环,有时候不是马上退出,需要等到cpu的控制权交还给线程的exec()。

一般在子线程退出的时候需要主线程去回收资源,可以调用QThread的wait,等待子线程的退出,然后回收资源.

2、Qt第二种创建线程方式

继承 QObject

实例化一个QThread对象

实现槽函数.

QObject子类对象通过moveToThread将自己放到线程QThread对象中.

调用QThread对象的start函数启动线程

必须通过发射信号来让槽函数在线程中执行,发射的信号存放在线程exec()消息队列中。

例如:

mywork.h

  #ifndef MYWORK_H  #define MYWORK_H  #include <QThread>  #include <QDebug>  class MyWork : public QObject  {   Q_OBJECT  public slots:   void workSlot()   {    qDebug() << "QThread begin" << endl;    qDebug() << "child thread" << QThread::currentThreadId() << endl;    QThread::sleep(5);    qDebug() << "QThread end" << endl;   }  };  #endif // MYWORK_H

widget.cpp

  #include <QApplication>  #include <QThread>  #include <QDebug>  #include "mywork.h"  ​  int main(int argc, char** argv)  {   qDebug() << "main thread" << QThread::currentThreadId() << endl;   QApplication app(argc, argv);   QThread thread;   MyWork work;   work.moveToThread(&thread);   QObject::connect(&thread, SIGNAL(started()), &work, SLOT(workSlot()));   thread.start();      QThread::sleep(6);   qDebug() << "thread is runing" << thread.isRunning() << endl;   thread.quit(); //调用quit让线程退出消息循环,否则线程一直在exec循环中   thread.wait(); //调用完quit后紧接着要调用wait来回收线程资源   qDebug() << "thread is runing" << thread.isRunning() << endl;  ​   return app.exec();  }

需要特别注意的是:

  1. 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过quit()退出线程exec()。
  2. QObject派生类对象,将要调用moveToThread,不能指定一个主线程父对象托管内存。
  3. QWidget的对象及派生类对象都只能在GUI主线程运行,不能使用moveToThread移到子线程中,即使没有指定父对象。

多线程对象内存释放

既然QObject对象无法托管内存对象,那么到底是先释放线程对象,还是先释放这个QObject对象?

先把QObject在线程循环中释放(使用QObject::deleteLater函数),然后QThread::quit,然后QThread::wait。

例如:

​mywork.h

  #ifndef MYWORK_H  #define MYWORK_H  ​  #include <QThread>  #include <QDebug>  class MyWork : public QObject  {   Q_OBJECT  public:  ​   ~MyWork() { qDebug() << __FUNCTION__ << endl; }  public slots:   void workSlot()   {    while(1)    {     qDebug() << "Work begin" << endl;     QThread::sleep(5);     qDebug() << "work end" << endl;    }   }   void otherWorkSlot()   {    qDebug() << "otherWork begin" << endl;    QThread::sleep(5);    qDebug() << "otherWork end" << endl;   }  ​  ​  };  ​  #endif // MYWORK_H

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/484372.html

(0)
上一篇 2020年11月10日
下一篇 2020年11月10日

精彩推荐