多线程
QThread 线程类是实现多线程的核心类。 Qt 有两种多线程的方法,其中一种是继承 QThread的 run()函数,另外一种是把一个继承于 QObject 的类转移到一个 Thread 里。 Qt4.8 之前都是使用继承 QThread 的 run()这种方法,但是 Qt4.8 之后, Qt 官方建议使用第二种方法。两种方法区别不大,用起来都比较方便,但继承 QObject 的方法更加灵活。 所以 Qt 的帮助文档里给的参考是先给继承 QObject 的类,然后再给继承 QThread 的类。
另外 Qt 提供了 QMutex、 QMutexLocker、 QReadLocker 和 QWriteLocker 等类用于线程之间的同步,详细可以看 Qt 的帮助文档
继承 QThread 的线程

run()方法是继承于 QThread 类的方法,用户需要重写这个方法,一般是把耗时的操作写在这个 run()方法里面
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
| #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QThread> #include <QDebug> #include <QPushButton>
class WorkerThread; class MainWindow : public QMainWindow { Q_OBJECT
public: MainWindow(QWidget *parent = nullptr); ~MainWindow();
private: WorkerThread *workerThread;
QPushButton *pushButton;
private slots: void handleResults(const QString &result);
void pushButtonClicked(); };
class WorkerThread : public QThread { Q_OBJECT
public: WorkerThread(QWidget *parent = nullptr) { Q_UNUSED(parent); }
void run() override { QString result = "线程开启成功";
sleep(2); emit resultReady(result); } signals: void resultReady(const QString &s); }; #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
| #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { this->setGeometry(0, 0, 800, 480); pushButton = new QPushButton(this); workerThread = new WorkerThread(this); pushButton->resize(100, 40); pushButton->setText("开启线程");
connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString))); connect(pushButton, SIGNAL(clicked()),this, SLOT(pushButtonClicked())); }
MainWindow::~MainWindow() { workerThread->quit();
if (workerThread->wait(2000)) { qDebug()<<"线程已经结束! "<<endl; } } void MainWindow::handleResults(const QString &result) { qDebug()<<result<<endl; } void MainWindow::pushButtonClicked() { if (!workerThread->isRunning()) workerThread->start(); }
|
继承 QObject 的线程

耗时的线程放入QThread线程里面。
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QThread> #include <QDebug> #include <QPushButton> #include <QMutexLocker> #include <QMutex>
class Worker; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: QPushButton *pushButton1; QPushButton *pushButton2; QThread workerThread; Worker *worker; private slots: void pushButton1Clicked(); void pushButton2Clicked(); void handleResults(const QString &); signals: void startWork(const QString &); };
class Worker : public QObject { Q_OBJECT private: QMutex lock; bool isCanRun; public slots: void doWork1(const QString ¶meter) { isCanRun = true; while (1) { { QMutexLocker locker(&lock); if (!isCanRun) { break; } } QThread::sleep(2); emit resultReady(parameter + "doWork1 函数"); } emit resultReady("打断 doWork1 函数"); }
public:
void stopWork() { qDebug()<<"打断线程"<<endl;
QMutexLocker locker(&lock); isCanRun = false; } signals:
void resultReady(const QString &result); }; #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 "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { this->setGeometry(0, 0, 800, 480); pushButton1 = new QPushButton(this); pushButton2 = new QPushButton(this); pushButton1->setGeometry(300, 200, 80, 40); pushButton2->setGeometry(400, 200, 80, 40); * 设置两个按钮的文本 */ pushButton1->setText("开启线程"); pushButton2->setText("打断线程"); worker = new Worker; worker->moveToThread(&workerThread); connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(&workerThread, SIGNAL(finished()), &workerThread, SLOT(deleteLater())); connect(this, SIGNAL(startWork(QString)), worker, SLOT(doWork1(QString))); connect(worker, SIGNAL(resultReady(QString)),this, SLOT(handleResults(QString))); connect(pushButton1, SIGNAL(clicked()), this, SLOT(pushButton1Clicked())); connect(pushButton2, SIGNAL(clicked()), this, SLOT(pushButton2Clicked())); } MainWindow::~MainWindow() { worker->stopWork(); workerThread.quit(); if (workerThread.wait(2000)) { qDebug()<<"线程结束"<<endl; } } void MainWindow::pushButton1Clicked() { const QString str = "正在运行"; if(!workerThread.isRunning()) { workerThread.start(); }
emit this->startWork(str); } void MainWindow::pushButton2Clicked() {
if(workerThread.isRunning()) {
worker->stopWork(); } } void MainWindow::handleResults(const QString & results) { qDebug()<<"线程的状态: "<<results<<endl; }
|