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

 

  • 5
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在PyQt5中使用QThread创建线程时,确保线程安全性非常重要。如果线程不安全,可能会导致资源争用、竞争条件和死锁。 要实现线程安全退出,需要在代码中实现以下几个步骤: 1. 创建一个类,该类继承自QObject和QThread,并重写run()方法。 2. 添加一个信号,当线程退出时发出,该信号作为通知主线程的指示器。 3. 在run()方法中,添加一个while循环,检查一个布尔值,该值表示程序是否应该继续运行。如果此布尔值为False,则跳出循环,结束线程。 4. 在mainwindow的析构函数中,将该布尔值设置为False,并通过emitsignal()方法发送信号,通知线程停止。 例如,以下是一个简单的例子,可以在主线程和PyQt5 QThread线程之间创建一种安全退出: ``` from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject class Worker(QThread): exitThread = pyqtSignal() def __init__(self, parent=None): super(Worker, self).__init__(parent) def run(self): while True: if not self.isRunning(): return #线程执行代码 def stop(self): self.exitThread.emit() class MainWindow(QWidget): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.workerThread = Worker() self.workerThread.exitThread.connect(self.stopThread) self.workerThread.start() def stopThread(self): self.workerThread.terminate() ``` 在上面的代码中,如果从mainwindow发送emit信号,emit将调用worker stop,从而启动信号退出方法exitThread,从而终止QThread中的运行。这将确保一个线程安全退出的模式,防止资源泄漏或竞争条件。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值