如何避免使用QProcess的waitForStarted来阻止GUI冻结?

时间:2016-07-25 20:00:06

标签: c++ qt qprocess

我正在使用QProcess运行wscript来运行VB脚本,该脚本将Excel文件转换为制表符分隔的文本文件。该脚本运行良好,但是GUI冻结,用户无法与其进行大量时间的交互。这是代码:

/* Create txt files and store paths */
for (int i = 0; i < excelFilepaths.size(); ++i) {    
    wscript->start("wscript.exe", QStringList() << vbs.fileName() << excelFilepaths.at(i) << newDir.absolutePath() + "/" + QString::number(i + 1));
    wscript->waitForFinished();
    payloadPaths.push_back(newDir.absolutePath() + "/" + QString::number(i + 1));
}

最近发生的事情是我有多个excel文件路径和堆上分配的QProcess。此QProcess运行VB脚本,将excel文件转换为文本文件,然后存储新文本文件的路径。这需要很长时间(4个excel文件大约需要20秒)。在此期间,GUI被冻结。我希望用户能够使用不干扰过程的GUI部分。

现在我怀疑这个问题的原因是

QProcess::waitForFinished()

我已经在线阅读有关连接QProcess的finished()和error()信号以解决此问题的信息。但是我一直很难这样做。我正在运行此代码作为继承自QObject并包含Q_OBJECT宏的类的方法,因此应该设置所有内容。我只是需要一些帮助将剩下的部分组合在一起。我怎样才能使它在QProcess运行时我的GUI不会冻结?请帮忙。

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题但 QSerialPort 。但是,我认为解决方案是一样的。我找不到让“serial-&gt; waitForReadyRead()”不冻结GUI的方法,所以,我实现了自己的功能。

void Research::WaitSerial(int MilliSecondsToWait)
{
    QTime DieTime = QTime::currentTime().addMSecs(MilliSecondsToWait);
    flag = 0;
    while(QTime::currentTime() < DieTime && !flag)
    {
        QCoreApplication::processEvents(QEventLoop::AllEvents,100);
        if(BufferSerial != "")
        {
            flag++;
        }
    }
}

当然,你的问题很相似但不一样。只需更改if即可获得“停止条件”。希望这会有所帮助。

编辑:这本来不是我的意思。我在某个论坛上发现了它。所以我不接受学分。

答案 1 :(得分:1)

引用名为Synchronous Process API的部分的文档:

  
      
  • waitForStarted()阻止,直到流程开始。
  •   
  • waitForReadyRead()阻止,直到新数据可用于在当前读取通道上读取。
  •   
  • waitForBytesWritten()阻塞,直到将一个数据有效负载写入进程。
  •   
  • waitForFinished()阻止,直到流程结束。
  •   
     

从主线程(调用QApplication :: exec()的线程)调用这些函数可能会导致用户界面冻结。

记住这一点。但是,您可以使用that

之类的内容克服此问题
connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus){ /* ... */ });

请注意,还有一些signals可能符合任何目的。