Версия для печати темы
Форум на CrossPlatform.RU _ Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие _ Помогите пожалуйста наладить перехват stdout консольного приложения.
Автор: Gordey 1.7.2010, 20:48
Всем привет.
Помогите пожалуйста наладить перехват stdout консольного приложения.
Использую QT 4.6.3 и Microsoft Visual Studio 2008.
Задача: из Qt GUI запустить консольное приложение, перехватить его стандартный поток ввода/вывода и вывести перехваченные данные в элемент QTextEdit.
Консольное приложение в цикле валит в поток вывода строки
Value: 1
Value: 2
Value: 3
и т.д.
#include <iostream>
int main(int argc, char* argv[])
{
for(int i =0; i != 1000000; ++i)
std::cout << "Value: " << i << std::endl;
return 0;
}
В Qt GUI при нажатии на кнопку создается отдельный поток.
process = new QProcess;
process->setProcessChannelMode(QProcess::MergedChannels);
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(output()));
process->start("test_console.exe");
exec();
При создании потока запускаем процесс с консольным приложением. При получении сигнала readyReadStandardOutput() отправляем считанные данные родительскому приложению.
void ServerThread::output()
{
QByteArray bytes = process->readAllStandardOutput();
emit updateOutput(bytes);
}
В Qt GUI получаем посылку с данными и выводим ее в QTextEdit.
void MainWindow::setOutput(const QString &msg)
{
ui->textEdit->insertPlainText(msg);
}
Проблема в том, что при перехвате потока ввода/вывода и выводе данных в QTextEdit происходит залипание Qt GUI. То есть я практически ничего не могу сделать с родительским окном.
Как можно решить данную проблему? Как избавиться от залипания QT окна? При решении проблемы изменять код консольного приложения нельзя , нужно решить задачу другими способами.
PS: Прикладываю тестовые проекты приложений. Так как проекты тестовые строго не судите за код… Обработки завершения процессов и потоков я не делал. Для распаковки архива с примерами удалите ".txt".
Автор: Gordey 1.7.2010, 21:26
Дополнительно выложил файлы проектов на webfile.ru
http://webfile.ru/4590573
Автор: Litkevich Yuriy 1.7.2010, 21:44
читай по форуму темы типа "потоки и сигналы", чтобы разобраться в каком конкретно потоке исполняется слот и т.п.
П.С. вопрос не в первый раз поднимается.
Автор: Gordey 1.7.2010, 22:03
Цитата(Litkevich Yuriy @ 1.7.2010, 22:44)
читай по форуму темы типа "потоки и сигналы", чтобы разобраться в каком конкретно потоке исполняется слот и т.п.
П.С. вопрос не в первый раз поднимается.
Да вроде бы все перерыл. Отчаявшись решил вот у гуру спросить.
Если ты знаешь решение проблемы уж подскажи пожалуйста, а не отсылай в далекие дали. Я там уже был, но не встретил того что мне нужно.
Автор: Litkevich Yuriy 1.7.2010, 22:28
яб для начала, отправлял бы всё в отладочную консоль (с помощью qDebug), вместо отображения в виджете. тут можно было бы сразу сказать тормозит ли виджет от потока данных или всё таки проблемы с потоками выполнения кода.
Автор: Gordey 2.7.2010, 6:08
Цитата(Litkevich Yuriy @ 1.7.2010, 23:28)
яб для начала, отправлял бы всё в отладочную консоль (с помощью qDebug), вместо отображения в виджете. тут можно было бы сразу сказать тормозит ли виджет от потока данных или всё таки проблемы с потоками выполнения кода.
Если я комментирую вывод информации в виджет, то тормоза пропадают.
void MainWindow::setOutput(const QString &msg)
{
// ui->plainTextEdit->insertPlainText(msg);
}
Залипание можно убрать если после вывода строки поставить задержку Sleep(1).
Старый вариант:
int main(int argc, char* argv[])
{
for(int i =0; i != 1000000; ++i)
std::cout << "Value: " << i << std::endl;
return 0;
}
Новый вариант:
int main(int argc, char* argv[])
{
for(int i =0; i != 1000000; ++i)
{
std::cout << "Value: " << i << std::endl;
Sleep(1);
}
return 0;
}
Но такой вариант мне не подходит так как консольное приложения я изменить не могу.
Автор: Litkevich Yuriy 2.7.2010, 11:50
Цитата(Gordey @ 2.7.2010, 10:08)
Но такой вариант мне не подходит так как консольное приложения я изменить не могу.
а зачем ты в него вообще полез, если оно неизменяемое? Про него и забудь.
Видимо для TextEdit это слишком большой темп поступления данных. Можно попробовать буферировать его, хотя я сомневаюсь, что это поможет. Скорее всего придётся менять сам виджет.
Автор: Gordey 2.7.2010, 15:31
Цитата(Litkevich Yuriy @ 2.7.2010, 12:50)
Видимо для TextEdit это слишком большой темп поступления данных. Можно попробовать буферировать его, хотя я сомневаюсь, что это поможет. Скорее всего придётся менять сам виджет
А что значит менять? Как его можно изменить чтобы он быстрее работал?
Автор: Litkevich Yuriy 2.7.2010, 16:22
Цитата(Gordey @ 2.7.2010, 19:31)
А что значит менять?
на какой-нибудь другой виджет.
Автор: Gordey 2.7.2010, 17:29
Цитата(Litkevich Yuriy @ 2.7.2010, 17:22)
TextEdit
Ааа... Я уже разные перепробовал.
Автор: Gordey 4.7.2010, 8:11
Неужто здесь на форуме нет гуру способных помочь?
Автор: Алексей1153 4.7.2010, 9:34
Цитата(Gordey @ 2.7.2010, 9:08)
Если я комментирую вывод информации в виджет, то тормоза пропадают.
void MainWindow::setOutput(const QString &msg)
{
// ui->plainTextEdit->insertPlainText(msg);
}
а если накапливать данные в std::vector<char> , а закидывать их с контрол не чаще чем, скажем, раз в 250 мс ? Причём, если очередное обновление запоздало, то основной процесс пускай подпинывает обновление контрола из вектора по таймеру
Автор: inviZ 4.7.2010, 13:13
Gordey, может попробуешь QPlainTextEdit? Он попроще. Все-таки QTextEdit достаточно сложный с кучей плюшек всяких и поэтому тормозной.
Автор: Gordey 4.7.2010, 14:35
Цитата(inviZ @ 4.7.2010, 14:13)
Gordey, может попробуешь QPlainTextEdit? Он попроще. Все-таки QTextEdit достаточно сложный с кучей плюшек всяких и поэтому тормозной.
Пробовал уже. На первый взгляд никаких изменений не увидел.
Цитата(Алексей1153 @ 4.7.2010, 10:34)
Цитата(Gordey @ 2.7.2010, 9:08)
Если я комментирую вывод информации в виджет, то тормоза пропадают.
void MainWindow::setOutput(const QString &msg)
{
// ui->plainTextEdit->insertPlainText(msg);
}
а если накапливать данные в std::vector<char> , а закидывать их с контрол не чаще чем, скажем, раз в 250 мс ? Причём, если очередное обновление запоздало, то основной процесс пускай подпинывает обновление контрола из вектора по таймеру
И так уже пробовал. Не помогает. Посылки приходят уже большого размера.
Автор: Litkevich Yuriy 4.7.2010, 14:55
я склоняюсь к тому, что при большом темпе поступления данных, в Qt будут проблемы. Т.к. вопрос о медленной отрисовке шрифтов в Qt уже не однократно поднимался.
Могу ещё для эксперимента несколько идей подкинуть:
1) обрамлять вставку данных в виджет функцией setUpdatesEnabled(bool)
2) задать виджету фиксированный размер, чтобы не заставлять компоновщик обсчитывать геометрию.
Автор: Gordey 4.7.2010, 18:54
Цитата(Litkevich Yuriy @ 4.7.2010, 15:55)
я склоняюсь к тому, что при большом темпе поступления данных, в Qt будут проблемы. Т.к. вопрос о медленной отрисовке шрифтов в Qt уже не однократно поднимался.
Могу ещё для эксперимента несколько идей подкинуть:
1) обрамлять вставку данных в виджет функцией setUpdatesEnabled(bool)
2) задать виджету фиксированный размер, чтобы не заставлять компоновщик обсчитывать геометрию.
Спасибо за идеи. Попробую.
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)