使用完成信号退出 Qt 中的线程并进行 clean_up 的正确方法
Posted
技术标签:
【中文标题】使用完成信号退出 Qt 中的线程并进行 clean_up 的正确方法【英文标题】:The correct way to exit a thread in Qt with finished signal and make clean_up 【发布时间】:2014-04-24 12:01:57 【问题描述】:我的应用程序有很多线程。我想在关闭主应用程序时退出线程并调用线程析构函数进行必要的清理。
Class Thread :public QThread
Thread();
run()
while(1)
//do work
~Thread()
//want to make clean up
;
Class my_app :public QCoreapplication
my_app()
Thread th1;
connect(&th1,SIGNAL(finished()),&th1,deleteLater());
connect(&th1,SIGNAL(finished()),&th1,quit());
;
//And my th1 thread runs in while.So I know that is the problem it runs on while and never emits the finished signal
//How can be achievable?
【问题讨论】:
您确定要这样做吗?谨防过早停止。 【参考方案1】:-
Do not subclass QThread
在工作循环中提供一些线程安全标志,指示工作人员应该结束其工作。
在终止应用程序之前,您应该调用QThread::wait 以确保线程在应用程序终止之前正常结束。
【讨论】:
如果“优雅终止”无关紧要怎么办?如果线程已经被阻塞调用,等待它终止可能需要很长时间,导致应用程序无法关闭并且无响应。 worker 可以持有一些重要的资源:文件、网络连接和其他东西。以正确的方式结束线程将使您免受文件损坏(丢失数据)、正确连接结束等错误的影响。此外,许多测试工具不会报告错误警报。 'worker 可以持有一些重要的资源' - 'can'。如果您可以设计使它们不这样做,则没有必要“优雅地终止”线程:) 线程的非优雅终止,即。当操作系统在进程终止时停止它们时,它确实有一个重要的优势 - 无论线程的状态如何,它总是可以工作,即使它正在另一个内核上运行。 是的,系统会清理大部分内容,但它不能做所有事情,例如向服务器发送一些关闭序列,或向外部设备发送关闭指令。即使您没有这种空间情况,最好在应用程序中进行全面清理,这样一些工具(如 valgrind)可以提供有用的报告而不会出现误报。【参考方案2】:在您的运行函数中,while 循环将导致您的线程永远不会停止,除非您自己管理线程终止,例如:
Class Thread :public QThread
Thread();
protected:
void run()
while(1)
if(this->finishThread==true)
return;
private:
bool finishThread;
你最好从 QObject 派生你的类并使用 moveToThread。您可以在类的构造函数中执行此操作:
th = new QThread();
this->setParent(0);
this->moveToThread(th);
clientSocket.moveToThread(th);
QObject::connect(th,SIGNAL(started()),this,SLOT(OnStarted()));
QObject::connect(th,SIGNAL(finished()),this,SLOT(OnFinished()));
th->start();
您的初始化和终止任务应分别在 OnStarted() 和 OnFinished() 槽中完成。
在你的类的析构函数中添加:
th->quit();
th->wait();
【讨论】:
'th->wait();' - 如果线程已经被某个地方阻塞了? @MartinJames Easy:向th->wait()
提供非零参数:th->quit(); th->wait(500); if (!th->isFinished()) th->terminate();
以上是关于使用完成信号退出 Qt 中的线程并进行 clean_up 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章