gpt4 book ai didi

c++ - 停止 Qt 线程 : calling exit() or quit() does not stop the thread execution

转载 作者:太空狗 更新时间:2023-10-29 20:22:23 24 4
gpt4 key购买 nike

在 main() 中创建了一个 QThread,即主线程。将 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”完成并且线程正常退出之前,我想从主线程中停止该线程。用过,

  1. 线程->退出()并在主线程中等待 (thread->wait())。
  2. thread->quit()并在主线程中等待 (thread->wait())。

  3. “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

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

最佳答案

isInterruptionRequested 仅当您调用了 QThread::requestInterruption 时才返回 true,不是 QThread::quit .这已记录在案。

如果你想使用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 完成之前 quit() 它的线程。

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 线程 : calling exit() or quit() does not stop the thread execution,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38022167/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com