I'm trying to kill/cancel a QThread. I followed the implementation of https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
I create the QThread like this:
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();
and try to stop it on a certain UI event by calling:
workerThread->quit();
My worker looks like this:
class ImageProcessor : public QObject
{
Q_OBJECT
public:
explicit ImageProcessor(QObject *parent = 0);
~ImageProcessor();
signals:
void finished();
public slots:
void process();
private:
//...
};
Where process calls an API with heavy calculations
void ImageProcessor::process()
{
// API call...
emit finished();
}
My problem is, that after calling quit on the thread, the thread keeps running ie the calculations of the API don't stop. Because the worker only calls the API, I cannot work with a cancel check in the worker loop. Any ideas?
Thanks in advance!
QThread will notify you via a signal when the thread is started() and finished(), or you can use isFinished() and isRunning() to query the state of the thread. You can stop the thread by calling exit() or quit(). In extreme cases, you may want to forcibly terminate() an executing thread.
To use it, prepare a QObject subclass with all your desired functionality in it. Then create a new QThread instance, push the QObject onto it using moveToThread(QThread*) of the QObject instance and call start() on the QThread instance. That's all.
Your heavy task is so simple that I would use QtConcurrent::run
and forget about QThread.
ImageProcessor* worker = new ImageProcessor();
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
QtConcurrent::run(worker, &ImageProcessor::process);
This does exactly what you need and it will be even a bit faster since it will use thread from thread pool, instead creating a new thread.
Just remember to use Qt::AutoConnection
(default value).
To stop processing gracefully you have to do a poling of some variable in your process method:
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();
}
If you have something like this, without any loop:
void ImageProcessor::process()
{
worker_api(); // that takes a lot of time
emit finished();
}
There is little you can do with QThread. You can do, from probably better to worst:
QProcess
and kill
it when no longer needed. Pros: no worries about clean-up. Contras: retrieving results may be difficult.QThread::terminate
, but is unadvised (see the warnings in the documentation: basically, no clean-up).QThread::currentThreadId
gives you a number you may be able to use with other OS calls (see the warnings in the documentation).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With