我尝试告诉线程优雅地退出。为此,线程在每次迭代中检查一个全局布尔标志,该标志指示线程是应该继续还是退出。线程设置如下(代码来自http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/):
ImageFusionQt::ImageFusionQt(QWidget* parent)
: QMainWindow(parent)
{
captureThread = new QThread();
captureWorker = new CaptureWorker();
// Connects the threads started() signal to the process() slot in the worker, causing it to start.
connect(captureThread, SIGNAL(started()), captureWorker, SLOT(process()));
// Connect worker finished signal to trigger thread quit, then delete.
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()));
connect(captureWorker, SIGNAL(finished()), captureWorker, SLOT(deleteLater()));
// Make sure the thread object is deleted after execution has finished.
connect(captureThread, SIGNAL(finished()), captureThread, SLOT(deleteLater()));
// Give QThread ownership of Worker Object
captureWorker->moveToThread(captureThread);
captureThread->start();
}
CaptureWorker.cpp
void CaptureWorker::process()
{
while(true)
{
g_exit_lock->lockForRead();
if( g_exit )
{
g_exit_lock->unlock();
break;
}
g_exit_lock->unlock();
}
qDebug() << "CaptureWorker: Exiting.";
emit finished();
}
现在,当我尝试通过在某个函数中将标志设置为true来停止线程时,process()方法返回但是线程没有完成并且对wait()的调用永远阻塞。为什么我的帖子没有终止?
g_exit_lock->lockForWrite();
g_exit = true;
g_exit_lock->unlock();
QThread::sleep(15);
qDebug() << "ct finished? " << captureThread->isFinished();
captureThread->wait();
qDebug() << "All threads stopped.";
日志文件输出:
2013.03.26 09:29:22[D] CaptureWorker: Exiting.
2013.03.26 09:29:37[D] ct finished? false
更新
我做了一些调试,发现了一些有趣的东西:
我的结论
打开问题
答案 0 :(得分:2)
这里发生的是quit
根本没有被调用。
你知道Qt有直接连接或排队连接。当你使用这个
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()));
它真的是一种自动连接类型。因此,因为您将captureWorker移动到另一个线程,所以使用了Qt::QueuedConnecton。将在主主题上调用quit()
。但你所做的是用captureThread->wait();
来阻止主线程
quit()
在事件循环中排队,但它被阻止,因为它等待线程完成。
所以你可能想直接调用quit(),比如替换
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()));
与
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()), Qt::DirectConnection);
或者像编辑中建议的那样直接调用quit(),或者如果你真的需要,你也可以执行以下操作而不是captureThread->wait();
QEventLoop l;
l.connect(captureThread, SIGNAL(finished()), SLOT(quit()));
l.exec(QEventLoop::ExcludeUserInputEvents);
或者你可以连接到线程的完成()信号并在captureThread->wait();
之后做你想做的事情,这样你就不必手动等待了。
在Qt
答案 1 :(得分:0)
问题是你实际上阻塞了主线程和事件循环,因此结果不让线程接收退出信号。 这个问题将通过以下方式解决:
g_exit_lock->lockForWrite();
g_exit = true;
g_exit_lock->unlock();
QThread::sleep(15);
qDebug() << "ct finished? " << captureThread->isFinished();
// You are missing below line, without this, main thread will block
captureThread->quit();
captureThread->wait();
qDebug() << "All threads stopped.";