QT程序退出还占进程

问题情况

程序运行时的样子:
在这里插入图片描述
程序退出时的样子:
其跑到了后台进程里面:
程序退出了,但在任务管理器里查看,其从进程里面转移到后台进程了。
这种问题,怎么办,代码里,应该释放的也都释放了,为什么会出这个问题呢?
在后台的进程,还有时占些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()可以请求中断。
这个功能可以用来使长时间运行的任务干净地中断。 建议在耗时长的运行函数中定期执行此操作。 注意不要太频繁地调用,以保持较低的开销。
最后,以一张图来说明情况:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/maokexu123/article/details/130098867