Как читать вывод QProcess - PullRequest
2 голосов
/ 31 мая 2019

В основном потоке приложения с графическим интерфейсом я запускаю QProcess другого приложения с графическим интерфейсом, которое со временем будет записывать некоторые сообщения в стандартный вывод с помощью fputs (). Проблема в том, что через некоторое время приложение с графическим интерфейсом, запущенное с QProcess, замерзнет, ​​потому что его вывод не используется родителем. Я знаю, что это проблема, потому что, если я запускаю QProcess с аргументом QIODevice :: NotOpen или QIODevice :: Unbuffered, он не застрянет, но вывод никогда не будет достигнут. Я попытался соединить сигналы 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);

Код подпроцесса, который будет входить в стандартный вывод:

QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);

Код полученного сообщения:

 if (!p) { // p is the QProcess
    return;
}
QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString()); 

Этот подход работает при запуске сценария оболочки или другой простой программы.

1 Ответ

0 голосов
/ 24 июня 2019

Я выяснил, в чем проблема в моем случае: Поскольку я запускал QProcess в std::Thread, события (сигналы), которые происходят, были пропущены, потому что std::Thread не имеет очереди событий, как QThread или QApplication. Решение, которое я использую: 1. Используйте QThread вместо std::thread 2. Время от времени звоните QCoreApplication::proccesEvents().

Правильным решением является использование QThread::exec() для создания event loop, но этот подход заблокирует приложение с графическим интерфейсом, поэтому в моем случае это не хорошо.

...