关于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();
}