解决在readyReadStandardOutput中用QThread::msleep导致的软件崩溃问题

在项目中,我需要在控制台中读取到对应的输出信息后,对事件进行延迟处理,这里我首先想到用msleep休眠函数,代码如下:

connect(RestoreFactoryProcess,&QProcess::readyReadStandardOutput,this,[this,&RestoreFactoryLoop,&RestoreFactoryData,&IfRestoreFactorySuccess,&RestoreFactoryProcess,&IfRestore,&qstrl]()
    {
        //读取通道内所有内容
        RestoreFactoryData=QString::fromLocal8Bit(RestoreFactoryProcess->readAllStandardOutput());

        qstrl<<RestoreFactoryData;
        QString slToStr=qstrl.join("");

        AddLog.AddLogText(RestoreFactoryData.toStdString());
        int count = 0;
        //判断是否恢复出场设置
        if(RestoreFactoryData.contains("json_cmd 3"))
        {
            QThread::msleep(3000);
            eventloop.exec();
            AddLog.AddLogText("restore success");
            IfRestoreFactorySuccess = true;
            IfRestore = true;
            RestoreFactoryProcess->close();
            RestoreFactoryProcess->kill();
            RestoreFactoryLoop.quit();
        }
    }

但此时运行软件会出现如下问题:在检测到包含json_cmd 3后,软件会直接闪退,此时我想会不会是QThread的msleep函数对多进程造成了影响,于是我去网上搜索了相应的问题。

以下是问题解析:

在Qt中,QThread::msleep() 是用来让当前线程休眠指定毫秒数的函数,通常用于处理异步任务,避免主线程阻塞。然而,在readyReadStandardOutput 这个信号连接上直接使用 msleep 可能会导致问题。

readyReadStandardOutput 是当标准输出(如控制台)中有数据可用时,会发送的一个信号。如果你在线程中接收到这个信号,并且立即使用 msleep,可能会造成以下问题:

  1. 阻塞事件循环:如果主线程正在等待这个信号,而你又让该线程睡眠,这可能导致主线程无法响应其他输入和UI更新,最终可能导致用户界面冻结,用户体验变差。

  2. 资源泄露:长时间的休眠可能导致线程资源(比如锁或者其他全局资源)无法及时释放,进而影响其他线程的正常工作。

  3. 潜在的死锁:在某些情况下,如果其他线程正试图访问同一资源并持有互斥锁,而你的线程在休眠,那么可能会形成死锁。

为了避免这类问题,你应该在处理完readyReadStandardOutput中的数据后再考虑是否需要暂停线程,或者将IO操作与线程睡眠分开,确保主线程的流畅性。如果确实需要线程暂停,可以考虑使用更合适的同步机制,例如条件变量(QWaitCondition)或者将IO操作移动到新的单独线程中。

于是解决方法就简单了,既然有安全隐患,那就不用这种方法了,于是我采用了事件循环机制来实现延迟处理,运行软件发现不会再闪退了。

connect(RestoreFactoryProcess,&QProcess::readyReadStandardOutput,this,[this,&RestoreFactoryLoop,&RestoreFactoryData,&IfRestoreFactorySuccess,&RestoreFactoryProcess,&IfRestore,&qstrl]()
    {
        //读取通道内所有内容
        RestoreFactoryData=QString::fromLocal8Bit(RestoreFactoryProcess->readAllStandardOutput());

        qstrl<<RestoreFactoryData;
        QString slToStr=qstrl.join("");

        AddLog.AddLogText(RestoreFactoryData.toStdString());
        int count = 0;
        //判断是否恢复出场设置
        if(RestoreFactoryData.contains("json_cmd 3"))
        {
            //QThread::msleep(3000);readyReadStandardOutput中使用可能会导致软件崩溃

            QEventLoop eventloop;
            QTimer::singleShot(5000, &eventloop, SLOT(quit()));
            eventloop.exec();

            AddLog.AddLogText("restore success");
            IfRestoreFactorySuccess = true;
            IfRestore = true;
            RestoreFactoryProcess->close();
            RestoreFactoryProcess->kill();
            RestoreFactoryLoop.quit();
        }
    }

通过使用一个事件循环,达到延迟5秒的实现效果,创建步骤如下:

  • 创建事件循环
  • 启动定时器,让其100ms后触发事件循环的quit()槽
  • 启动事件循环

所以在处理进程相关的代码里,还是要注意一些休眠函数的问题的,比如msleep,如果放在函数开头或结尾,是不会出现软件崩溃问题的,但如果是放在QProcess::readyReadStandardOutput中,可能会导致相应的信号处理出现异常,从而导致程序崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值