退出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();
}
但是,这将在等待工作人员完成时"冻结"您的应用程序。如果要在等待时保持响应,请改用 MyApplication::stopWorker
中的本地QEventLoop
,并将其用作:
MyApplication::stopWorker() {
QEventLoop stopLoop;
connect(m_threadWorker, &QThread::finished,
&stopLoop, &QEventLoop::quit);
QMetaObject::invokeMethod(m_worker, "quit");
stopLoop.exec();
m_threadWorker->deleteLater();
}
感谢您的评论,此解决方案有效
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()),Qt::QueuedConnection);
connect(m_worker, SIGNAL(finished()), m_threadWorker, SLOT(quit()),Qt::DirectConnection);
connect(m_threadWorker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
m_threadWorker->start();
m_window->show();
}
MyApplication::~MyApplication()
{
m_threadWorker->wait();
m_threadWorker->deleteLater();
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()";
}