執行緒暫停與終止

如果想要停止執行緒,QThread有個terminate()方法,但是這個方法會直接停止執行緒,無論現在是在流程的哪個位置,這會使得一些資源的善後工作無法完成,可能導致不可預期的程式錯誤,因此不建議使用。

一個執行緒要停止,基本上就是執行完run()函式,此時系統會幫我們清除線程實例。但有時可能run()函式執行的是一個無窮迴圈,由使用者提供訊息,程式接收到訊息後才終止執行緒。


這邊的範例有兩個按鈕,一個開啟執行緒,一個關閉執行緒,程式內部有個stopped變數,在run()方法中,while迴圈由stopped變數來判斷是否繼續迴圈。

thread.h

#ifndef THREAD
#define THREAD

#include <QThread>
#include <QDebug>

class Thread : public QThread {
    Q_OBJECT

public:
    Thread();
    void stop();
protected:
    void run();
private:
    bool stopped;
};

#endif

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QCloseEvent>
#include "thread.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
public slots:
    void startThread();
    void stopThread();
protected:
    void closeEvent(QCloseEvent *event);
private:
    QPushButton *startBtn;
    QPushButton *stopBtn;
    QHBoxLayout *layout;
    Thread *thread;
};

#endif 

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent) : 
    QWidget(parent)
{
    setWindowTitle(tr("按鍵組"));
    layout = new QHBoxLayout(this);
    startBtn = new QPushButton(tr("開啟執行緒"));
    stopBtn = new QPushButton(tr("關閉執行緒"));
    layout->addWidget(startBtn);
    layout->addWidget(stopBtn);

    startBtn->setEnabled(true);
    stopBtn->setEnabled(false);

    thread = new Thread();
    connect(startBtn,SIGNAL(clicked()),this,SLOT(startThread()));
    connect(stopBtn,SIGNAL(clicked()),this,SLOT(stopThread()));
}

void Widget::startThread() {
    thread->start();
    startBtn->setEnabled(false);
    stopBtn->setEnabled(true);
}

void Widget::stopThread() {
    if(thread->isRunning()){
        thread->stop();
    }
    stopBtn->setEnabled(false);
    startBtn->setEnabled(true);
}
void Widget::closeEvent(QCloseEvent *event) {
    thread->stop();
    thread->wait();
    event->accept();
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

  • QThread的wait()方法,會等待執行緒完成,再進行接下來的動作,也可以指定wait()的時間,時間到時就進行接下來的動作。