c – 停止Qt线程:调用exit()或quit()不会停止线程执行

在main()即主线程中创建了一个QThread.
将一个worker类移动到新线程.该线程执行worker类的’StartThread’方法.

工人线程:

//header file
class Worker : public QObject
{
    Q_OBJECT
public:
    Worker(QThread* thread);

public slots:
    void StartThread(); 
    void EndThread();

private:
    QThread* m_pCurrentThread;
};


// source file
#include "QDebug"
#include "QThread"
#include "worker.h"

Worker::Worker(QThread* thread)
{
m_pCurrentThread = thread;
}

void Worker::StartThread()
{
    qDebug() << " StartThread";

    while(true)
    {
        QThread::msleep(1000);
        qDebug() << " thread running";
        static int count = 0;
        count++;
        if(count == 10)
        {            
            break;
        }
        if(m_pCurrentThread->isInterruptionRequested())
        {
            qDebug() << " is interrupt requested";
            // Option 3:  
            m_pCurrentThread->exit();               
        }
    }
    qDebug() << "StartThread finished";
}

void Worker::EndThread()
{
    qDebug() << "thread finished";
}

Main.cpp的

#include <QCoreApplication>
#include "worker.h"
#include "QThread"
#include "QObject"
#include "QDebug"

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

    QThread* thread = new QThread();
    Worker* workerObj = new Worker(thread);

    QObject::connect(thread,
                     SIGNAL(started()),
                     workerObj,
                     SLOT(StartThread()));
    QObject::connect(thread,
                     SIGNAL(finished()),
                     workerObj,
                     SLOT(EndThread()));



    workerObj->moveToThread(thread);
    thread->start();
    thread->requestInterruption();
    QThread::msleep(2000);
    qDebug() << "terminate thread";
    if(thread->isRunning())
    {   
        // Option 1,2 exit() / quit() used but got same output
        thread->exit(); 
        qDebug() << "wait on  thread";
        thread->wait();
    }
    qDebug() << " exiting main";

    return a.exec();
}

现在,在’StartThread’完成并正常退出线程之前,我想从主线程中停止线程.
用过的,

> thread-> exit()
并在主线程中等待(thread-> wait()).
> thread-> quit()
并在主线程中等待(thread-> wait()).
>’StartThread’中的exit()

预期:
 一旦从主线程调用exit()/ quit(),线程执行就应该停止.

实际:
 在所有三个实例中,线程一直在运行,完成’StartThread’方法并正常退出.尽管没有调用exit()/ quit().
   输出:

StartThread
 thread running
 is interrupt requested
terminate thread
wait on  thread
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
 is interrupt requested
 thread running
StartThread finished
thread finished
exiting main

是否可以在主线程需要时停止/处理线程?

最佳答案
如果您调用了QThread :: requestInterruption而不是QThread :: quit,则isInterruptionRequested仅返回true.这是记录在案的.

如果你想使用QThread :: quit,线程必须旋转一个事件循环,所以你不应该从它派生;而是这样做:

class Worker : public QObject {
  QBasicTimer m_timer;
  int chunksToDo = 20;
  void doChunkOfWork() {
    QThread::sleep(1);
  }
  void timerEvent(QTimerEvent * ev) {
    if (ev->timerId() != m_timer.timerId()) return;
    if (!chunksToDo) { m_timer.stop(); return; }
    doChunkOfWork();
    if (!--chunksToDo) emit done();
  }
public:
  explicit Worker(QObject * parent = nullptr) : QObject{parent} {
    m_timer.start(0, this);
  }
  Q_SIGNAL void done();
};

要运行worker,请创建它并将其移动到某个线程.要停止worker,只需在worker完成之前退出()它的线程.

int main(int argc, char ** argv) {
  QCoreApplication app{argc, argv};
  Worker worker;
  QThread thread;
  worker.moveToThread(&thread);
  QObject::connect(&worker, &Worker::done, &thread, &QThread::quit);
  QObject::connect(&thread, &QThread::finished, &app, &QCoreApplication::quit);
  thread.start();
  return app.exec();
}

您可能希望使用线程池,而不是手动管理线程的生命周期.

class Worker : public QObject, QRunnable {
  int chunksToDo = 20;
  volatile bool active = true;
  void doChunkOfWork() {
    QThread::sleep(1);
  }
  void run() {
    while (active && chunksToDo) {
      doChunkOfWork();
      --chunksToDo;
    }
    emit done();
  }
public:
  using QObject::QObject;
  Q_SLOT void stop() { active = false; }
  Q_SIGNAL void done();
};

int main(int argc, char ** argv) {
  QCoreApplication app{argc, argv};
  QThreadPool pool;
  Worker worker;
  worker.setAutoDelete(false); // important!
  pool.start(&worker);
  // *
  QTimer::singleShot(5000, &worker, &Worker::stop);
  QObject::connect(&worker, &Worker::done, &app, &QCoreApplication::quit);
  return app.exec();
}

在不运行主事件循环的情况下结束它的另一种方法是:

  // *
  QThread::sleep(5);
  worker.stop();
  pool.waitForDone();
}

This answer有一个将多个作业流式传输到线程池的完整示例.

点击查看更多相关文章

转载注明原文:c – 停止Qt线程:调用exit()或quit()不会停止线程执行 - 乐贴网