關於QT退出線程,一直迷迷糊糊的,湊活着能用就行,出了問題總覺得莫名其妙,現在靜下心來總結一下。
感謝
線程運行有兩種方式
#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();
}