如何避免使用 QProcess 的 waitForStarted 来阻止 GUI 冻结?
How to avoid waitForStarted with QProcess to stop GUI from freezing?
我正在 运行使用 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 运行s VB 脚本将 excel 文件转换为文本文件,然后存储新文本文件的路径。这需要很长时间(4 excel 个文件大约需要 20 秒)。在此期间,GUI 被冻结。我希望用户能够使用不干扰进程的 GUI 部分。
现在我怀疑这个问题的原因是
QProcess::waitForFinished()
而且我已经在线阅读了有关连接 QProcess 的 finished() 和 error() 信号以消除此问题的信息。但是我一直很难这样做。我将此代码 运行 设置为 class 的方法,它继承自 QObject 并包含 Q_OBJECT 宏,因此应设置所有内容。我只需要一些帮助来将其余部分放在一起。我怎样才能使我的 GUI 在 QProcess 运行ning 时不冻结?请帮忙
我遇到了同样的问题,但是 QSerialPort。但是,我认为解决方案是相同的。我找不到让 "serial->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
更改为您的 "stopping condition"。希望这有帮助。
编辑:这不是我最初的想法。我在某处的论坛上找到了它。所以我不收学分。
在名为 Synchronous Process API 的部分引用文档:
waitForStarted()
blocks until the process has started.
waitForReadyRead()
blocks until new data is available for reading on the current read channel.
waitForBytesWritten()
blocks until one payload of data has been written to the process.
waitForFinished()
blocks until the process has finished.
Calling these functions from the main thread (the thread that calls QApplication::exec()) may cause your user interface to freeze.
记住这一点。但是,您可以使用 that:
之类的方法来解决此问题
connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus){ /* ... */ });
请注意,还有一些 signals 可能适合任何所需的目的。
我正在 运行使用 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 运行s VB 脚本将 excel 文件转换为文本文件,然后存储新文本文件的路径。这需要很长时间(4 excel 个文件大约需要 20 秒)。在此期间,GUI 被冻结。我希望用户能够使用不干扰进程的 GUI 部分。
现在我怀疑这个问题的原因是
QProcess::waitForFinished()
而且我已经在线阅读了有关连接 QProcess 的 finished() 和 error() 信号以消除此问题的信息。但是我一直很难这样做。我将此代码 运行 设置为 class 的方法,它继承自 QObject 并包含 Q_OBJECT 宏,因此应设置所有内容。我只需要一些帮助来将其余部分放在一起。我怎样才能使我的 GUI 在 QProcess 运行ning 时不冻结?请帮忙
我遇到了同样的问题,但是 QSerialPort。但是,我认为解决方案是相同的。我找不到让 "serial->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
更改为您的 "stopping condition"。希望这有帮助。
编辑:这不是我最初的想法。我在某处的论坛上找到了它。所以我不收学分。
在名为 Synchronous Process API 的部分引用文档:
waitForStarted()
blocks until the process has started.waitForReadyRead()
blocks until new data is available for reading on the current read channel.waitForBytesWritten()
blocks until one payload of data has been written to the process.waitForFinished()
blocks until the process has finished.Calling these functions from the main thread (the thread that calls QApplication::exec()) may cause your user interface to freeze.
记住这一点。但是,您可以使用 that:
之类的方法来解决此问题connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus){ /* ... */ });
请注意,还有一些 signals 可能适合任何所需的目的。