Qt-如何杀死QThread

Qt-如何杀死QThread,qt,Qt,我正在尝试终止/取消一个QThread。我跟踪了该计划的实施情况 我创建的QThread如下所示: workerThread = new QThread(); ImageProcessor* worker = new ImageProcessor(); worker->moveToThread(workerThread); connect(workerThread, SIGNAL(started()), worker, SLOT(process())); connect(worker, S

我正在尝试终止/取消一个QThread。我跟踪了该计划的实施情况

我创建的QThread如下所示:

workerThread = new QThread();
ImageProcessor* worker = new ImageProcessor();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
class ImageProcessor : public QObject
{
Q_OBJECT
public:
explicit ImageProcessor(QObject *parent = 0);
~ImageProcessor();

signals:
void finished();

public slots:
void process();

private:
//...
};
并尝试通过调用以下命令在某个UI事件上停止它:

workerThread->quit();
我的工人看起来像这样:

workerThread = new QThread();
ImageProcessor* worker = new ImageProcessor();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
class ImageProcessor : public QObject
{
Q_OBJECT
public:
explicit ImageProcessor(QObject *parent = 0);
~ImageProcessor();

signals:
void finished();

public slots:
void process();

private:
//...
};
其中,进程调用一个计算量很大的API

void ImageProcessor::process()
{
// API call...

emit finished();
}
我的问题是,在线程上调用quit之后,线程继续运行,即API的计算不会停止。因为worker只调用API,所以我无法在worker循环中使用cancel检查。有什么想法吗

提前谢谢

API的计算没有停止

所以你在计算的时候试图阻止它

QThread::quit仅在计算完所有内容后停止

您可以将计算拆分为更小的任务,甚至可以添加取消标志。在ImageProcessor对象上使用普通方法进行设置:

class ImageProcessor{
   void stop(){
     canceled = true;
   }
private:
   bool canceled;
}
然后检查是否(取消)退货;在进程槽中。(只写bool是线程安全的)


然后调用stop();无法停止已阻止的QThread,至少不能以任何安全方式停止

例如,如果您已输入此函数

void neverStop() {
    int *arr = new int[1024*1024];
    for (;;) {
    }
}

线程不会响应任何退出消息,虽然大多数操作系统都有强制终止线程的方法,但任何分配的内存都不会被正确释放。

不要使用
thread->quit()。通过这种方式,您可以从内部正确地停止工作程序,例如停止处理并发出finished()信号

您可以通过在工作程序中实现用于取消的插槽(例如
插槽\u cancelWorker()
)来设置该标志。然后,您可以将其与GUI连接:

connect(myPushButton, SIGNAL(clicked()), worker, SLOT(slot_cancelWorker()));

当然,在处理函数中,必须检查挂起的事件。因此,您必须定期调用
QCoreApplication::processEvents()

您繁重的任务非常简单,我会使用
QtConcurrent::run
而忘记QThread

ImageProcessor* worker = new ImageProcessor();
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
QtConcurrent::run(worker, &ImageProcessor::process);
这正是您所需要的,而且速度会更快,因为它将使用线程池中的线程,而不是创建一个新线程

只需记住使用
Qt::AutoConnection
(默认值)

要优雅地停止处理,您必须在处理方法中对某些变量进行极化:

bool ImageProcessor::needEndNow() {
    QMutexLocker locker(mutex);
    return endNowRequested;
}

void ImageProcessor::requestEndNow() {
    QMutexLocker locker(mutex);
    endNowRequested = true;
}

void ImageProcessor::process()
{
   while(!needEndNow()) {
       // nextStep of processing
   }

   emit finished();
}

如果您有类似的东西,没有任何循环:

void ImageProcessor::process()
{
    worker_api(); // that takes a lot of time
    emit finished();
}
对于QThread,您几乎无能为力。你可以做,从更好到最坏:

  • 可能您正在使用的API有另一个调用来停止该工作调用。但是既然你在这里问,我想没有这样的事情
  • 在不再需要时,使用
    QProcess
    kill
    从不同的进程启动辅助进程调用。优点:不用担心清洁。相反:检索结果可能很困难
  • QThread::terminate
    ,但未经建议(请参阅:基本上,无清理)
  • 在Windows中,
    QThread::currentThreadId
    为您提供了一个可以用于其他操作系统调用的号码(请参阅)

这里的问题是,我只调用一个进行大量计算的API函数。我不能把它分解成更小的碎片,因此也不能检查它是否被取消。API开始了它自己的生活,我不知道如何阻止它…为什么不让它运行呢?如果调用
workerThread->setPriority(QThread::IdlePriority)
它也不会使用很多resource…您可以运行线程直到结束,如果
cancelled
为true,则不会发出完成信号。看看这个答案-,它可能对您有用