QThread線程的運行和退出

關於QT退出線程,一直迷迷糊糊的,湊活着能用就行,出了問題總覺得莫名其妙,現在靜下心來總結一下。

感謝

QThread的用法:開啓與退出

Qt QThread 這是我 見過解析最全面的一片文章

 

線程運行有兩種方式

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QLoggingCategory>

/* Qt的線程可以多次啓用 
     
   這是第一種方式,使用 QObject::MoveToThread()
    1.創建你的工作類 Worker,必須繼承於 QObject
    2.創建你的執行類 Controller,類內聲明 QThread變量thread
    3.在Controller內將 Worker執行 MoveToThread(QThread* thd)
    4.在Controller內connect其他信號到運行函數(我的是work())。運行函數內如果是死循環,則需要自己加退出標誌,然後通過其他函數操作這個變量,使死循環退出。
    5.啓動 (我的 Controller ::Start() )
    6.需要時停止 (我的 Controller::Stop )
*/

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr)  : QObject(parent) {}
    bool quit = false;
    int index = 0;
    void work()
    {
        index = 0;
        while (!quit) {
            index++;
            qDebug() << "i'm working " << index;
            QThread::msleep(500);
        }
        qDebug() << "worker:" << QThread::currentThread();
        quit = false;
    }
};


class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = nullptr)  : QObject(parent)
    {
        worker.moveToThread(&thread);
        connect(this, &Controller::sig_Started, &worker, &Worker::work);
    }
    virtual ~Controller() {}

    Worker worker;
    QThread thread;


    void Start()
    {
        //線程函數啓動,不能在此直接調用worker.work(),需要有connect連接一下才能將該函數放到線程之內運行
        thread.start();
        emit sig_Started();
    }
    void Stop(){
        qDebug() << "ready to exit";
        worker.quit = true;
        thread.wait();
        qDebug() << "exit done";
    }

signals:
    void sig_Started();
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "thread is "  << QThread::currentThread();

    Controller ctl;
    ctl.move2thd();
    ctl.Start();


    //10s後退出
    QThread::sleep(10);
    qDebug() << "main call thread quit";
    ctl.Stop();

    //再次啓動
    qDebug() << "start again";
    ctl.Start();
    //10s後退出
    QThread::sleep(15);
    qDebug() << "main call thread quit";
    ctl.Stop();


    return a.exec();
}

 

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QLoggingCategory>

/* Qt的線程可以多次啓用 
    這是第二種方式 
    1.定義一個繼承於 QThread的類,類內實現函數 
        void run() override;  //你的線程執行內容
    2.如果你的不是死循環,可以在 run() 內直接執行,如果是死循環,可以用上面第一種方式的 死循環+退出標誌位 的方式寫,也可以使用定時器的方式
    3.定時器的方式。在 run() 函數內啓動定時器,這個定時器是在當前線程上啓動的,而非主線程。 run() 函數的最後一行記得加上  exec(),使線程啓動消息循環,這樣不用自己再加退出標誌變量。此時線程函數已開始執行。
    4.如果需要停止,在其他地方調用 exit() wait(),必須在上一步執行了exec(),線程才能收到 exit()

*/


class Work2 : public QThread
{
    Q_OBJECT
public:
    Work2(QObject* parent = nullptr): QThread(parent){}
    ~Work2() { ptm->deleteLater(); }

    int index = 0;
    void tmot()
    {
        index++;
        qDebug() << "thread is " << QThread::currentThread();
        qDebug() << "i'm working " << index;
    }
    QTimer* ptm = nullptr;
    void run() override
    {
        index = 0;
        ptm = new QTimer();
        bool res = connect(ptm, &QTimer::timeout, this, &Work2::tmot, Qt::DirectConnection);
        ptm->start(500);
        exec();
    }
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "thread is "  << QThread::currentThread();

    Work2 work2;
    work2.start();

    //10s後退出
    QThread::sleep(10);
    qDebug() << "main call thread quit";
    work2.exit();
    work2.wait();

    //再次啓動
    qDebug() << "start again";
    work2.start();
    //10s後退出
    QThread::sleep(15);
    qDebug() << "main call thread quit";
    work2.exit();
    work2.wait();


    return a.exec();
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章