Russian Qt Forum
Ноябрь 23, 2024, 08:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: Процесс внутри потока?  (Прочитано 31298 раз)
chron1c
Гость
« : Март 06, 2012, 01:21 »

Доброго времени суток.
Собственно, проблема:
Есть класс для процесса и для потока.
Класс потока:
Код:
//========== processtree.h
class ProcessTree : public QThread
{
        Q_OBJECT
public:
        void setTree(QTreeWidget *i);
protected:
        QTreeWidget *tree;
        void run();
private:
        bool checkPing(const QString *str);
};
//======== processtree.cpp
void ProcessTree::run()
{
        QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
        MyShell *test = new MyShell;
        test->start(*iterator);
}
 
void ProcessTree::setTree(QTreeWidget *item, MyShell *p)
{
        tree = item;
}


Через setTree принимает указатель на QtreeWidget, в своей переменной запоминает его.
Далее создаётся итератор и в процесс передаётся указатель на QTreeWidgetItem. Итератор создаю, т.к. потом планирую по очереди каждый QTreeWidgetItem в tree перебрать. ( вообще, нужно проверить пингуется ли комп, айпишник которого лежит в text(0) в каждом QTreeWidgetItem.

Класс процесса:

Код:
//=========== H
class MyShell : public QProcess {
Q_OBJECT
signals:
        void pFinished(bool result);
public:
        MyShell(QWidget *pwgt = 0);
        void start(QTreeWidgetItem *i);
public slots:
        void slotDataOnStdout();
private slots:
        void finalize(bool result);
private:
        QProcess *m_process;
        QTreeWidgetItem *item;
};
//============= CPP
MyShell::MyShell(QWidget *pwgt) : QProcess(pwgt)
{
        item = 0;
        m_process = new QProcess(this);
        connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(slotDataOnStdout()));
        connect(this, SIGNAL(pFinished(bool)), SLOT(finalize(bool)));
}
 
void MyShell::start(QTreeWidgetItem *i)
{
        item = i;
        item->setText(1, "Started");
        m_process->start("cmd /C ping "+item->text(0));
}
 
void MyShell::slotDataOnStdout()
{
                item->setText(1, "inSTD"); //Это просто проверка, получен ли сигнал
                QString *output = new QString(m_process->readAllStandardOutput());
                if(output->indexOf("TTL") < 0) emit finished(false);
                else emit pFinished(true);
/*Здесь ещё раньше ставил m_process->kill(), т.к. пингуется ли айпи можно понять по первой строчке вывда, а ждать, если не пингуется, пока выведет все "Превышен ..." не хочется. Расчитывал убивать процесс, а потом, в цикле в потоке, запускать его снова. Не знаю уж, нормально это или быдлокод, с потоками и процессами первый раз столкнулся. Посоветуете, может, что-нибудь? */
}
 
void MyShell::finalize(bool result)
{
        if(result) item->setText(0, "OWNED!!!"); //Опять проверка
        else item->setText(0, "FAIL :(");
}


По каким-то причинам процесс не высылает readyReadStandardOutput(), ну или его не получает slotDataOnStdout(). Пробовал в главном потоке процесс создавать и родителем его делать QWidget, а не QProcess ( в примере, по которому учился он был с ГУИ и с родителем QWidget ), но тогда придётся заморачиваться с сигналами и слотами между потоками, да и вообще мне как-то сложно представить как тогда задачу свою решить.
Может, можно и как-нибудь иначе сделать то, что мне нужно, но с Qt я работаю буквально пару дней, так что, естественно, многого не знаю.
Записан
neversleep
Гость
« Ответ #1 : Март 06, 2012, 05:33 »

Зачем вообще парится с процессом? Юзай винапи ф-цию IcmpSendEcho или т.н raw sockets.
Записан
chron1c
Гость
« Ответ #2 : Март 06, 2012, 11:57 »

Я в этом понимаю ещё меньше, чем в Qt, т.е. вообще ничего Улыбающийся
По ТЗ нужно сделать именно на Qt, да и уже просто интересно почему в моём случае не работает. Столько провозился и времени столько потерял, что теперь, не разобравшись, забивать как-то не хочется.
Записан
Bepec
Гость
« Ответ #3 : Март 06, 2012, 12:02 »

минимально компилируемый проект в архив и в студию.
Записан
chron1c
Гость
« Ответ #4 : Март 06, 2012, 12:57 »

Комментарии внутри.
Чуть не забыл, пишу его в VS2008 с Add-In'ом Qt4.6.
« Последнее редактирование: Март 06, 2012, 12:59 от chron1c » Записан
Bepec
Гость
« Ответ #5 : Март 06, 2012, 13:21 »

Отвечаю - интересная реализация конечно потоков...

Первое
Тебя не насторожили надписи в Output

Код:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0xa7bd18), parent's thread is QThread(0x3e9270), current thread is ProcessTree(0x12fec8)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0xa7bd18), parent's thread is QThread(0x3e9270), current thread is ProcessTree(0x12fec8)

Которые вылетают на строчке

Код:
m_process->start("cmd /C ping "+item->text(0));


Мораль - ты создаёшь QProcess в 1 потоке, а потом пытаешься запустить во втором...Он и сопротивляется.

Второе
Очень интересная реализация потоков.

Код:
void ProcessTree::run()
{
/* -//-//-//-
*/
QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
process->start(*iterator);
           // А вот тут, после выполнения 1 функции start, поток умирает, если не вызвать к примеру QThread::run();
}

А по делу - читай про потоки, делай простенькие программки. Они тебе не будут терпеливо ждать, пока придёт ответ, выполнится QProcess. Он до конца run дойдёт и на кладбище.
Записан
chron1c
Гость
« Ответ #6 : Март 06, 2012, 13:43 »

На самом деле я даже не знаю как в этот Output заглянуть. С VS столько же, сколько и с Qt знаком. Раньше в блокноте писал всё.
Передавать адрес процесса я только сейчас стал, до этого было в ProcessTree:
Код:
	MyShell *test = new MyShell;
QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
test->start(*iterator);
И родителем у MyShell был QProcess, а не QWidget. (Если ставить QWidget, то ругается, что виджеты должны в ГУИ-потоке запускаться. )

После
Код:
process->start(*iterator);
думал, может, ставить
Код:
sleep(2);
или что-то такое, хоть корректным мне это и не кажется.
Как-то ведь можно поток заставить ждать пока не придёт сигнал от процесса? Так думал поступить. Ну и как в комментариях написал, то в теле run() хотел ставить бесконечный цикл, просто сейчас его там нет, т.к. на одном элементе даже не работает схема.

Интересная реализация, если с профессиональной точки зрения, то это, скорее, в плохом или хорошем смысле?
Записан
Bepec
Гость
« Ответ #7 : Март 06, 2012, 13:55 »

Я бы сказал честно - в отвратительном Улыбающийся

Понамешано всего(хотя понятно, новичок всё же).

А ты не пробовал к примеру создавать QProcess динамически внутри потока. И до тех пор, пока поток не обработает все NNN адресов, его не отпускать на кладбище?


Набросок на мой (возможно не оч профессиональный) взгляд:

Создаётся виджет, заполняется таблица с IP.

После чего тыкается кнопка и запускается поток. Поток каждый раз создаёт QProcess, ждёт его завершения и результатов, переходит к следующему. Как только адреса заканчиваются - заканчивается цикл и поток умирает. До тех пор, пока кто-то добрый не нажмёт кнопочку и снова не создаст экземпляр потока.


PS программа на 8,000-12,000 строк в блокноте, это, конечно, сильно.
Записан
chron1c
Гость
« Ответ #8 : Март 06, 2012, 14:00 »

Ну я именно так и хочу сделать. Процесс оказался в главном потоке только потому, что я проверял, будет ли хоть так работать. Как и выше написал, сейчас у меня так:
Код:
void ProcessTree::run()
{
MyShell *test = new MyShell; // <- Это разве не динамически создаётся?
QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
test->start(*iterator);
        /* Ну а здесь проверка на завершился ли процесс будет, а сейчас хоть бы для одного элемента заставить работать его. */
}
Записан
Bepec
Гость
« Ответ #9 : Март 06, 2012, 14:09 »

ну вызови ты в конце концов QThread::run();
Код:
void ProcessTree::run()
{
MyShell *test = new MyShell; // <- Это разве не динамически создаётся?
QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
test->start(*iterator);
        /* Ну а здесь проверка на завершился ли процесс будет, а сейчас хоть бы для одного элемента заставить работать его. */
            QThread::run();
}
Записан
chron1c
Гость
« Ответ #10 : Март 06, 2012, 14:46 »

О мой бог, как же я затупил. Спасибо!
Только сейчас дошло, что поток, завершившись, убивает и процесс, который просто не успевает завершиться.
Как я понимаю, поставив в конец run() - я зациклю поток. Но как заставить его перебирать итераторы? Хм. Почитал в ассистенте про QThread::run(), так и не понял, почему, поставив его в конец, всё заработало. У родителя( QThread ) не переопределён у меня же run(), => вызовется QThread::exec()? В доках написано, что он буде ждать, пока не получит exit(), но от кого он будет его ждать? И когда будет выслан exit()? Когда завершится процесс внутри ProcessTree?
Записан
Bepec
Гость
« Ответ #11 : Март 06, 2012, 14:54 »

QThread::run() делает поток "событийным", реагирующим только на вызовы извне и сигналы. Сам же он ждёт тихо тихо.

А exit() ему надо передавать самому(я так делаю, ибо потоки у меня опасные Подмигивающий ).

Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки. (Дурью маяться тяжелооо... Вот и будет йхенй страдать Подмигивающий )

ПОПРАВКА - зациклить на пустой цикл аля
Код:
while(true)
{}

Записан
BRE
Гость
« Ответ #12 : Март 06, 2012, 15:08 »

Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки.
Смеющийся Ты откуда это берешь? Почему он будет память жрать?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #13 : Март 06, 2012, 15:08 »

Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки. (Дурью маяться тяжелооо... Вот и будет йхенй страдать
Память? С чего бы ему память-то потреблять? У вас она течёт где-то?
Может вы загрузку процессора имели в виду?
Записан
Bepec
Гость
« Ответ #14 : Март 06, 2012, 15:12 »

вру вру ) Процессорное время Подмигивающий

Точнее даже не всего процессора, а 1 ядро Подмигивающий
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.096 секунд. Запросов: 23.