如何读取 QProcess 输出
How to read QProcess output
在 Gui 应用程序的主线程中,我正在启动另一个 GUI 应用程序的 QProcess,它将使用 fputs() 随着时间的推移在 stdout 中记录一些消息。问题是,一段时间后,使用 QProcess 启动的 GUI 应用程序将冻结,因为它的输出未被父进程使用。我知道这是问题所在,因为如果我用 QIODevice::NotOpen 或 QIODevice::Unbuffered 参数启动 QProcess,它不会卡住,但永远不会达到输出。
我尝试将子进程的 readyRead、readyReadStandardError、readyReadStandardOutput 信号连接到父进程中的一个插槽,但由于某些原因,信号从未发出。我也在每次写入后刷新标准输出。
我的问题是如何强制QProcess在不关闭的情况下实时发送一些数据?
信号的连接,(T- 是 QProcess 的包装器):
process->setWorkingDirectory(workingDir);
process->start(prog, argumentsList);
process->waitForStarted();
T* reciver = new V8QProcess(process);
QObject::connect(process, &QProcess::readyRead, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardError, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardOutput, reciver, &V8QProcess::OnMessageRecieved);
将登录 stdout 的子进程的代码:
QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);
OnMessageRecieved 代码:
if (!p) { // p is the QProcess
return;
}
QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString());
这种方法在 运行 shell 脚本或其他简单程序时有效。
我发现问题出在我的案例上:
因为我在 std::Thread
中启动 QProcess
,所以跳过了发生的事件(信号),因为 std::Thread
没有 QThread
或 QApplication
确实如此。
我使用的解决方案是:
1. 使用 QThread
而不是 std::thread
2、时不时调用QCoreApplication::proccesEvents()
正确的解决方案是使用 QThread::exec()
来创建一个 event loop
,但这种方法会阻止 GUI 应用程序,所以对我来说并不好。
在 Gui 应用程序的主线程中,我正在启动另一个 GUI 应用程序的 QProcess,它将使用 fputs() 随着时间的推移在 stdout 中记录一些消息。问题是,一段时间后,使用 QProcess 启动的 GUI 应用程序将冻结,因为它的输出未被父进程使用。我知道这是问题所在,因为如果我用 QIODevice::NotOpen 或 QIODevice::Unbuffered 参数启动 QProcess,它不会卡住,但永远不会达到输出。 我尝试将子进程的 readyRead、readyReadStandardError、readyReadStandardOutput 信号连接到父进程中的一个插槽,但由于某些原因,信号从未发出。我也在每次写入后刷新标准输出。 我的问题是如何强制QProcess在不关闭的情况下实时发送一些数据?
信号的连接,(T- 是 QProcess 的包装器):
process->setWorkingDirectory(workingDir);
process->start(prog, argumentsList);
process->waitForStarted();
T* reciver = new V8QProcess(process);
QObject::connect(process, &QProcess::readyRead, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardError, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardOutput, reciver, &V8QProcess::OnMessageRecieved);
将登录 stdout 的子进程的代码:
QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);
OnMessageRecieved 代码:
if (!p) { // p is the QProcess
return;
}
QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString());
这种方法在 运行 shell 脚本或其他简单程序时有效。
我发现问题出在我的案例上:
因为我在 std::Thread
中启动 QProcess
,所以跳过了发生的事件(信号),因为 std::Thread
没有 QThread
或 QApplication
确实如此。
我使用的解决方案是:
1. 使用 QThread
而不是 std::thread
2、时不时调用QCoreApplication::proccesEvents()
正确的解决方案是使用 QThread::exec()
来创建一个 event loop
,但这种方法会阻止 GUI 应用程序,所以对我来说并不好。