c++ - 如何使用工作线程正确退出 Qt 应用程序?
问题描述
退出 Qt 应用程序的最佳做法是什么?我做这样的事情
int main(int argc, char *argv[])
{
MyApplication app(argc, argv);
return myApp.exec();
}
MyApplication::MyApplication( int& argc, char** argv ) :
QApplication( argc, argv )
{
m_window= new MyWidget();
m_worker= new MyWorker();
m_threadWorker = new QThread;
m_worker->moveToThread(m_threadWorker);
connect(this, SIGNAL(aboutToQuit()),m_worker,SLOT(quit()));
connect(m_worker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
connect(m_worker, SIGNAL(finished()), m_threadWorker, SLOT(quit()));
connect(m_threadWorker, SIGNAL(finished()), m_threadWorker, SLOT(deleteLater()));
m_threadWorker->start();
m_window->show();
}
MyApplication::~MyApplication()
{
m_window->deleteLater();
qDebug()<<"MyApplication::~MyApplication()";
}
MyWorker::quit()
{
//longer ending operations freeing resources
emit finished();
qDebug() << "MyWorker::quit() emit finished()";
}
MyWorker::~MyWorker()
{
qDebug() << "MyWorker::~MyWorker()";
}
问题是 Worker 析构函数通常不会运行。我担心不正确地结束工作人员会不时导致应用程序崩溃。我在该线程中使用了一个摄像头,因此如果摄像头循环处于活动状态,则释放需要更多时间,并且通常永远不会发出完成的内容,因此永远不会调用析构函数。
解决方案
问题是aboutToQuit
不等待工人完成。您必须明确等待它这样做:
connect(this, &MyApplication::aboutToQuit,
this, &MyApplication::stopWorker);
// also, change up your connects a little to make shure everything gets deleted properly
connect(m_worker, &MyWorker::finished,
m_threadWorker, &QThread::quit,
Qt::DirectConnection); //direct connection is needed, because you are blocking the main thread by waiting
connect(m_threadWorker, &QThread::finished,
m_worker, &MyWorker::deleteLater);
MyApplication::stopWorker() {
QMetaObject::invokeMethod(m_worker, "quit");
m_threadWorker->wait();
m_threadWorker->deleteLater();
}
但是,这将在等待工作人员完成时“冻结”您的应用程序。如果您想在等待时保持响应,请改用本地QEventLoop
内部MyApplication::stopWorker
并将其用作:
MyApplication::stopWorker() {
QEventLoop stopLoop;
connect(m_threadWorker, &QThread::finished,
&stopLoop, &QEventLoop::quit);
QMetaObject::invokeMethod(m_worker, "quit");
stopLoop.exec();
m_threadWorker->deleteLater();
}
推荐阅读
- qt - QML:文本编辑+滚动视图:尝试显示大文本时,无法水平剪辑
- linux - 英特尔 SPDK ioat 示例无法运行
- r - 使用 dplyr 重新组织数据帧
- excel - 在单个宏运行时未检测到嵌入文件
- scala - 使用 scala/spark 从 Intellij 读取 S3 存储桶文件
- php - PHP脚本无法连接到MYSQL数据库
- android - 单击按钮时如何从一个活动切换到另一个活动
- javascript - 在对象数组中查找最大值
- tomcat - Tomcat 8.5 找不到 [jdbc]
- c++ - 从 c++ 对象动态创建 qml 对象(使用 setContextProperty)