众所周知Qt的多线程有两种方法(写起来有三种), 注意当线程存在死循环时(即使是waitcondition等待),则该线程的事件循环将会被阻塞
继承QThread 官方范例里面都没有说线程等待某一个事件的问题,查找文档之后发现有个QWaitCondition 很好用, 大概如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #ifndef INHERITQTHREAD_H #define INHERITQTHREAD_H #include <QThread> #include <QWaitCondition> #include <QMutex> #include <QDateTime> #include <QTimer> #include <QDebug> class InheritQThread : public QThread{ Q_OBJECT public : explicit InheritQThread (QObject *parent = 0 ) ; ~InheritQThread(); signals: public slots:private : QWaitCondition m_condition; QMutex m_mutex; bool m_quit; protected : void run () ; }; #endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include "inheritqthread.h" InheritQThread::InheritQThread (QObject *parent) : QThread (parent) { m_quit = false ; QTimer *t = new QTimer (this ); t->setTimerType (Qt::PreciseTimer); t->setInterval (1000 ); connect (t, &QTimer::timeout, [=](){ m_condition.wakeAll (); }); t->start (); } InheritQThread::~InheritQThread () { m_condition.wakeAll (); m_quit = true ; quit (); wait (); qDebug () << "线程退出完毕" ; } void InheritQThread::run () { while (true ){ if (m_quit){ break ; } m_mutex.lock (); m_condition.wait (&m_mutex); m_mutex.unlock (); for (int i = 0 ; i < 100000 ; i++){ } qDebug () << QDateTime::currentDateTime ().toString ("yyyy-MM-dd hh:mm:ss.zzz" ); } }
用一个父类包裹 下QThread, 分两种情况
使用Controller 和 Worker 然后通过信号槽来工作, 参见官方文档的例子1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Worker : public QObject{ Q_OBJECT public slots: void doWork (const QString ¶meter) { QString result; emit resultReady (result) ; } signals: void resultReady (const QString &result) ; }; class Controller : public QObject{ Q_OBJECT 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 (); } public slots: void handleResults (const QString &) ; signals: void operate (const QString &) ; };
将父类moveToThread,大概如下
调用时注意 ThreadContainer *c = new ThreadContainer; 不能有父对象 同时注意析构时删除 c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #ifndef THREADCONTAINER_H #define THREADCONTAINER_H #include <QObject> #include <QThread> #include <QTimer> #include <QMutex> class ThreadContainer : public QObject{ Q_OBJECT public : explicit ThreadContainer (QObject *parent = 0 ) ; ~ThreadContainer(); signals: public slots:private : QMutex m_mutex; bool m_quit; QThread *m_thread; QTimer *m_timer; public : void doWork () ; }; #endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include "threadcontainer.h" #include <QDateTime> #include <QDebug> ThreadContainer::ThreadContainer (QObject *parent) : QObject (parent) { m_quit = false ; m_thread = new QThread; m_thread->start (); moveToThread (m_thread); m_timer = new QTimer; m_timer->setTimerType (Qt::PreciseTimer); m_timer->setInterval (1000 ); connect (m_timer, &QTimer::timeout, this , [=](){ doWork (); }); m_timer->start (); qDebug () << "ThreadContainer" << QThread::currentThreadId (); } ThreadContainer::~ThreadContainer () { m_mutex.lock (); m_quit = true ; m_mutex.unlock (); m_thread->quit (); m_thread->wait (); delete m_thread; delete m_timer; qDebug () << "线程退出完毕" ; } void ThreadContainer::doWork () { QMutexLocker locker (&m_mutex) ; if (m_quit){ return ; } for (int i = 0 ; i < 100000 ; i++){ } qDebug () << QDateTime::currentDateTime ().toString ("yyyy-MM-dd hh:mm:ss.zzz" ) << QThread::currentThreadId (); }