Russian Qt Forum
Март 28, 2024, 19:35
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Вопросы новичков
>
Убийство процесса.
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Убийство процесса. (Прочитано 4274 раз)
FreshMeat
Гость
Убийство процесса.
«
:
Март 13, 2017, 09:46 »
Доброго времени суток!
Возникла следующая проблема: я писал фронтенд с графическим интерфейсом к консольному приложению. Помимо всего прочего, при закрытии он должен был убивать запущенный процесс консольного приложения, которое имеет свойство работать долго и использовать много ресурсов компьютера. Выглядит это так:
Есть класс главного окна, в котором в 'closeEvent' перед закрытием посылается сигнал 'Kill()';
Есть другой класс, унаследованный от 'QObject', внутри которого происходит вызов консольного приложения через 'QProcess', и объект которого после создания в главном окне помещается в отдельный поток;
Есть 'connect', связывающий сигнал главного окна 'Kill()' и слот второго класса 'Kill()' через 'Qt::DirrectConnection'. Проверено лично - после закрытия главного окна слот получает предназначенный ему сигнал - следовательно, главное окно со своей задачей справляется;
Во втором классе вызов консольного приложения происходит через функцию, в которую передаётся предварительно сформированная строка 'QString line' из имени и параметров запуска консольного приложения, далее внутри неё создаётся 'QProcess process' и стартует приложение 'process.start(line)', затем начинается цикл, в котором считывается вывод приложения, пока 'process.state()' не равно нулю;
Здесь появляется проблема - в этом же цикле идёт проверка глобальной логической переменной, истинное значение которой означает необходимость завершить программу: 'if(toKill)process.kill()'. Как понятно, в конструкторе класса прописана инициализация этой переменной нулём, а единицей она становится в слоте 'Kill()'. Казалось бы, всё готово для убийства процесса. Ан нет, после закрытия процесс продолжает работать как ни в чём не бывало.
Из всех попыток что-то изменить удалась только одна - поместить во второй класс глобальную переменную типа 'QProcess', в функции вызова вместо создания нового 'QProcess' сразу стартовать строку из глобального, в слот 'Kill()' сразу вызывать 'process.kill()'. Да, консольное приложение в этом случае закрывается, но при каждом новом вызове 'process.start(line)' выводится предупреждение вида:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0x5f9698), parent's thread is QThread(0xb037738), current thread is QThread(0xdad7780)
Вопрос - как же всё-таки грамотно реализовать убиение процесса?
«
Последнее редактирование: Март 13, 2017, 09:56 от FreshMeat
»
Записан
Пантер
Administrator
Джедай : наставник для всех
Offline
Сообщений: 5876
Жаждущий знаний
Re: Убийство процесса.
«
Ответ #1 :
Март 13, 2017, 09:59 »
Ты некорректно работаешь с процессом. Отдельный поток вообще не нужен. Вешайся на сигнал QProcess::readyReadStandardOutput и в слоте читай данные.
Записан
1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
FreshMeat
Гость
Re: Убийство процесса.
«
Ответ #2 :
Март 13, 2017, 14:28 »
Цитировать
Ты некорректно работаешь с процессом. Отдельный поток вообще не нужен.
Я его и не создаю, вроде как. Вот код той функции.
Код:
void MyClass::Run(QString line)
{
process.setReadChannel(QProcess::StandardError);
process.start(line);
do
{
process.waitForReadyRead(-1);
emit SendOut(process.readAllStandardError());
}
while(process.state());
}
Спросите, зачем wait? Просто мне необходимо дожидаться завершения работы.
Цитировать
Вешайся на сигнал QProcess::readyReadStandardOutput и в слоте читай данные.
Звучит как хорошая идея, но тогда как добиться ожидания конца работы? Через QEventLoop?
Записан
qate
Супер
Offline
Сообщений: 1175
Re: Убийство процесса.
«
Ответ #3 :
Март 13, 2017, 14:35 »
Цитата: FreshMeat от Март 13, 2017, 14:28
Звучит как хорошая идея, но тогда как добиться ожидания конца работы? Через QEventLoop?
при окончании работы qprocess выкинет сигнал
Записан
Пантер
Administrator
Джедай : наставник для всех
Offline
Сообщений: 5876
Жаждущий знаний
Re: Убийство процесса.
«
Ответ #4 :
Март 13, 2017, 14:38 »
FreshMeat, используй асинхронную работу с QProcess через сигналы/слоты.
Записан
1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
FreshMeat
Гость
Re: Убийство процесса.
«
Ответ #5 :
Март 13, 2017, 16:39 »
Цитата: qate от Март 13, 2017, 14:35
при окончании работы qprocess выкинет сигнал
Который сам по себе не тормозит выполнение остальной части кода. Или я не прав?
Цитата: Пантер от Март 13, 2017, 14:38
FreshMeat, используй асинхронную работу с QProcess через сигналы/слоты.
Уже пытаюсь организовать. Читая документацию Qt, узнал, что сигналы с сигналами можно коннектить, что упростило часть задачи. Теперь вот гадаю, как законнектить сигнал процесса на готовность чтения с
сигналом
второго класса на отправку строки вида 'SendLine(QString)', ведь нужно как-то указать, что отправить нужно именно содержимое выходного канала, а не просто QString.
Грубо говоря, на ум сразу напрашивается нечто подобное:
Код:
connect(&process,SIGNAL(readyReadStandartError()),this,SIGNAL(SendLine(QString)));
но так, чтобы в 'QString' попал 'process.readAllStandartError()'.
«
Последнее редактирование: Март 13, 2017, 17:04 от FreshMeat
»
Записан
FreshMeat
Гость
Re: Убийство процесса.
«
Ответ #6 :
Март 13, 2017, 17:30 »
В общем, соединив сигнал главного окна 'Kill()' с сигналом второго класса 'Kill()', а тот в свою очередь со слотом процесса 'kill()', я добился того, чего хотел - процесс теперь исправно закрывается с закрытием главного окна. Всем спасибо, все свободны.
Напоследок уточню - удалив первый пост, я удалю только его или всю тему?
Записан
Пантер
Administrator
Джедай : наставник для всех
Offline
Сообщений: 5876
Жаждущий знаний
Re: Убийство процесса.
«
Ответ #7 :
Март 14, 2017, 07:54 »
Не удаляй, вдруг, кому-то еще понадобится. А по поводу сигнала, сделай промежуточный слот, в котором вычитаешь данные и заэммитишь сигнал с ними.
Записан
1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
FreshMeat
Гость
Re: Убийство процесса.
«
Ответ #8 :
Март 14, 2017, 09:16 »
Цитата: Пантер от Март 14, 2017, 07:54
Не удаляй, вдруг, кому-то еще понадобится.
Хорошо, не буду.
Цитировать
А по поводу сигнала, сделай промежуточный слот, в котором вычитаешь данные и заэммитишь сигнал с ними.
Я сделал бы, если бы знал, как правильно взаимодействовать с 'sender()'-ом, ибо сигнал 'readyRead()' сам по себе ничего не отправляет. Его, наверное, можно было бы перегрузить ручками, но зачем, если циклическое чтение полностью удовлетворяет мои требования для данной задачи? Тут просто суть в том, что мне не нужна асинхронная работа процесса и объекта класса, его вызывающего, они должны выполняться по очереди, друг за другом. А раз так, к чему организовывать слот-сигнальные взаимодействия процесса и класса по отслеживанию завершения, готовности, когда можно просто пустить их в одном потоке, но отдельном от главного окна?
Впрочем, послушаю любой совет, как это дело облагородить.
Записан
Пантер
Administrator
Джедай : наставник для всех
Offline
Сообщений: 5876
Жаждущий знаний
Re: Убийство процесса.
«
Ответ #9 :
Март 14, 2017, 13:00 »
Отдельный поток тебе не нужен, я уже говорил об этом. Смотри пример. Создай класс ProcessCommunicator, в котором инкапсулируй QProcess, а наружу прокинь сигнал newLineAvailable(const QString &line). Это как вариант.
Записан
1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...