为什么我的线程不能优雅地退出?
Why do my threads not exit gracefully?
我试图告诉一个线程优雅地退出。为此,线程在每次迭代中检查一个全局布尔标志,该标志指示线程是应该继续还是退出。线程是这样设置的(代码来自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
我做了一些调试,发现了一些有趣的东西:
- 线程阻塞在它的事件循环(QEventLoop::exec)中。它等待一个quit()信号,它显然没有收到。
- 在 process()返回后创建线程的事件循环。通过像我这样连接信号,线程的run()方法在线程已经完成它的工作后被调用(例如process()返回)。
- 事件循环在执行实际循环之前清除所有发布的退出事件。
我的结论
- 像我一样连接quit()插槽不起作用,因为quit()事件在事件循环建立时被删除
- 直接在线程对象上调用quit()成员函数,显然会导致优雅的终止。这可以通过使用QThread::currentThread()->quit(); 从外部或从内部完成。
开放式问题
- 事件循环建立后是否有方法调用process()方法?
- 当工作已经完成时创建事件循环感觉是错误的。但是,我使用QThread的方式与docs 一致。
这里发生的是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);
或者你可以连接到线程的finished()信号,并在captureThread->wait();
之后做任何你想做的事情,这样你就不必手动等待了。
Qt中有很多方法
问题是您实际上阻塞了主线程和事件循环,因此不让线程接收退出信号。通过以下操作可以解决这个问题:
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.";
相关文章:
- 当我在main中声明了我的2d数组时,为什么我的程序会退出
- 为什么我的 c++ 代码在使用堆栈时以退出代码 11 结尾?
- 当if语句告诉程序返回0时,我的程序不会退出
- CLion 没有调试我的目标之一 - 立即"进程已完成,退出代码为 0"
- 试图调节我的 do-while 以停止在终端中退出程序.菜单不会根据需要循环使用当前语句
- 为什么我的构造函数在退出时引发分段错误
- 为什么我的 C++ 应用以退出值 -1 终止,但某些代码逻辑未执行?
- 为什么我的程序在 while 循环后退出
- 为什么GetMessage在不发送任何消息的情况下退出我的程序
- 我找不到第一个用户输入后立即退出程序的原因
- 为什么我的新分配指针会自动在程序退出上删除
- 我找不到导致我的数组在运行两次案例并退出后损坏的错误
- Gtk::在将我的gtkmm2移植到gtkmm3应用程序时,窗口显示并退出
- C++ 运行失败:退出值 2 - 我的代码出了什么问题?
- Eclipse在退出和/或启动(CDT)时编辑我的包含路径
- 为什么我的程序在调用main之前就退出了
- 为什么我的C++程序在使用 NULL 对象时静默退出
- 为什么我的安卓应用在线程退出时崩溃
- C++ exit(0) 在配置从调试更改为发布后不再立即退出我的程序
- 为什么我的所有C++程序都以0xc0000139退出