QT5以后官方推荐用moveToThread的方式实现多线程。
官方例子如下
class Worker : public QObject { Q_OBJECT //继承自QObject的工作类 public slots: void doWork(const QString ¶meter) { QString result; /* ... here is the expensive or blocking operation ... */ 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 &); };
这个实例有一个问题,当工作类任务结束后,无法结束工作线程释放资源,所以在工作类里加一个信号,当耗时操作完成后去通知主线程,在主线程中释放工作类和工作线程的资源。
修改一下如下:
class Worker : public QObject { Q_OBJECT public: ~Worker(){ qDebug() << "Worker 析构"; } public slots: void doWork(QString parameter){ //QString result; //emit resultReady(result);//工作类可以通过信号返回结果给控制类 emit finished();//自定义的工作类结束信号 } signals: void resultReady(const QString &result); void finished(); }; class Controller : public QObject { Q_OBJECT QThread workerThread; public: explicit Controller(){ Worker *worker = new Worker; worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, this, &QObject::deleteLater);//delete工作类 connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);//delete控制类 //控制类和工作类通过信号和槽交互 connect(this, &Controller::operate, worker, &Worker::doWork); connect(worker, &Worker::resultReady, this, &Controller::handleResults); connect(worker, &Worker::finished, [=]{ workerThread.quit(); workerThread.wait(); }); workerThread.start(); } ~Controller(){ qDebug() << "Controller析构"; } void test(QString str){ emit operate(str); } public slots: void handleResults(QString str); signals: void operate(QString str); };