解决程序退出后线程仍在后台运行的问题

解决程序退出后线程仍在后台运行的问题

问题情况

程序运行时的样子:

程序退出时的样子:

其跑到了后台进程里面:

程序退出了,但在任务管理器里查看,其从进程里面转移到后台进程了。

这种问题,怎么办,代码里,应该释放的也都释放了,为什么会出这个问题呢?

在后台的进程,还有时占些cpu,说明的确在运行,的确在做事情。

这首先怀疑到了是否线程的问题呢?

问题分析

1、线程析构了吗?

窗体的析构函数:

MainWindow::~MainWindow()

{

if(nullptr != m_pCmdThread)

{

m_pCmdThread->deleteLater();

delete m_pCmdThread;

}

线程的析构函数:

CmdThread::~CmdThread()

{

quit();

wait();

}

看着都正常,问题出在那呢?

可能是quit(),wait()

quit()

告诉线程的事件循环以return 0(成功)退出。 相当于调用QThread :: exit(0)。如果线程没有事件循环,这个函数什么也不做。

wait()

阻塞线程,直到满足以下任一条件:

与此QThread对象关联的线程已经完成执行(即从run()返回)。 如果线程完成,该函数将返回true。 如果线程尚未启动,它也返回true。

时间毫秒已经过去了。 如果时间是ULONG_MAX(默认值),那么等待永远不会超时(线程必须从run()返回)。 如果等待超时,此函数将返回false。

这里非常关键的解释是quit(),quit(),不是线程退出,而是线程的事件循环退出,如果是继承的QThread,那么,自己实现了run方法,里面也没调用exec()方法,则这一个线程没有事件循环,这一点必须清楚。

没有事件循环,那么run方法的死循环就退不出来,我的代码是这样写的:

void CmdThread::run()

{

qDebug("enter function CmdThread::run");

m_pCmdService = new CmdService();

QString strMessage;

while(true)

{

switch (this->m_currentState)

{

case INIT_PORT:

case OPEN_PORT:

if(!m_pCmdService->openPort(*this->m_pBoardInfoDomain))

{

strMessage = QString::asprintf("串口%s连接失败", this->m_pBoardInfoDomain->serialName.c_str());

emit sendMessage(1, strMessage);

return;

}

显然,是没有事件循环的,那这样,线程还是在一 直运行的,那么这种情况如何解决,方法很多,目的就是退出这一个while循环就可以了,其实也可以这样说,没有一个合适的方法退出正在运行的线程,如果强制退出,那样是危险的。

为了正式一些,就用官方推荐的方法如下:

void CmdThread::run()

{

qDebug("enter function CmdThread::run");

m_pCmdService = new CmdService();

QString strMessage;

while(true)

{

if(QThread::currentThread()->isInterruptionRequested())

{

break;

}

switch (this->m_currentState)

{

case INIT_PORT:

case OPEN_PORT:

if(!m_pCmdService->openPort(*this->m_pBoardInfoDomain))

{

strMessage = QString::asprintf("串口%s连接失败", this->m_pBoardInfoDomain->serialName.c_str());

emit sendMessage(1, strMessage);

return;

}

触发的事件如下:

CmdThread::~CmdThread()

{

requestInterruption();

quit();

wait();

}

就是在析构的时候停止线程。

这样,再测试发现,关闭窗体后,后台进程不会再存在了,这样就解决了这一个问题,这一个问题的关键点在于:

1、对quit,exit函数的理解,其是退出线程事件,不会退出线程的run方法

2、线程的退出,只能我自己写代码实现,没有其它的办法,在析构函数里退出就是一个很好的方法。

如果一个应该停止的任务在此线程上运行,则返回true。 requestInterruption()可以请求中断。

这个功能可以用来使长时间运行的任务干净地中断。 建议在耗时长的运行函数中定期执行此操作。 注意不要太频繁地调用,以保持较低的开销。

最后,以一张图来说明情况:

相关推荐

牛仔裤买回来要洗吗?新买的牛仔裤怎么洗? 神器365软件下载

牛仔裤买回来要洗吗?新买的牛仔裤怎么洗?

联金所怎么样? 我和大佬的365天第三季免费看

联金所怎么样?

如何在微信中删除照片,彻底清理聊天记录 365bet官网网投

如何在微信中删除照片,彻底清理聊天记录