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

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

Страниц: 1 2 3 [4] 5   Вниз
  Печать  
Автор Тема: Процесс внутри потока?  (Прочитано 31345 раз)
BRE
Гость
« Ответ #45 : Март 10, 2012, 13:10 »

процесс должен запускаться снова по окончанию предыдущего
Можно легко перезапускать.

нужно последовательное, а не параллельное выполнение.
Что-то мне подсказывает что это не так. Для чего тогда использовать потоки?

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #46 : Март 10, 2012, 13:23 »

нужно последовательное, а не параллельное выполнение.
Что-то мне подсказывает что это не так. Для чего тогда использовать потоки?
Ну это вопрос к chron1c Улыбающийся Я понял что опрос адресов выполнять в отдельной нитке - чтобы UI не замерзало, разумно. А натравить N ниток на все адреса - разговора не было.
Записан
BRE
Гость
« Ответ #47 : Март 10, 2012, 13:32 »

Ну это вопрос к chron1c Улыбающийся
Согласен. Улыбающийся

Я понял что опрос адресов выполнять в отдельной нитке - чтобы UI не замерзало, разумно.
Ну как бы QProcess прекрасно работает асинхронно, совсем не замораживая UI.
Записан
chron1c
Гость
« Ответ #48 : Март 10, 2012, 23:06 »

Дело не только в QProcess, нужно постоянно работать с элементами дерева, один за другим. И элементы будут удаляться/изменяться/добавляться. К тому же, далее планируется расширение программы ещё одним функционалом, поэтому в главном потоке хочется оставить минимум.
Гибкость, хм. Да, соглашусь с вами, хоть она мне тут и не нужна, но лишней не будет. Сделаю чтоб класс принимал QString.
В идеале, сделать бы в потоке просто цикл бесконечный, который продолжался бы переходил на следующую итерацию только после того как получит сигнал определённый. А когда итератор бы начинал указывать ни на что, то просто его пересоздавать, заставляя тем самым указывать на начало дерева снова. Сделать "бесконечный цикл" только сигналами и слотами представляется мне нереализуемым, т.к. сколько бы я не пытался, даже если по логике всё корректно, то не работало ничего.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #49 : Март 11, 2012, 10:36 »

В идеале, сделать бы в потоке просто цикл бесконечный, который продолжался бы переходил на следующую итерацию только после того как получит сигнал определённый. А когда итератор бы начинал указывать ни на что, то просто его пересоздавать, заставляя тем самым указывать на начало дерева снова.
Тогда передавайте во второй класс указатель на дерево а итератор делайте членом этого класса. В слоте SlotRеply присваиваете ему новый итератор как только старый закончился. Сделав второй маленький класс мы развязали себе руки, его легко менять как угодно, в этом гибкость.

Сделать "бесконечный цикл" только сигналами и слотами представляется мне нереализуемым, т.к. сколько бы я не пытался, даже если по логике всё корректно, то не работало ничего.
Все прекрасно получается если "бесконечный цикл" заменить на "бесконечный обмен сигналами"  Улыбающийся

..в главном потоке хочется оставить минимум.
Это желание понятно, но не следует претворять его в жизнь буквально, типа "больше кода/логики должно быть перенесено в др нитки"
Записан
chron1c
Гость
« Ответ #50 : Март 12, 2012, 20:38 »

Хм. Попробовал так:
Код:
#include "pingstring.h"
#include <QProcess>
PingString::PingString()
{
mProcess = 0;
}

void PingString::takeOutput()
{
QString *output = new QString(mProcess->readAllStandardOutput());
        mProcess->kill();
        //delete mProcess;
bool result = false;
if(output->contains("TTL")) result = true;
delete output;
emit pingResult(result);
}

void PingString::pingAdress(const QString &text)
{
mProcess = new QProcess;
connect(mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(takeOutput()));
mProcess->start("cmd /C ping "+(text));
}
Код:
#include "iplistiterator.h"
#include <QTreeWidget>
#include <QTreeWidgetItemIterator>

IplistIterator::IplistIterator(QTreeWidget *pTree, QObject *parent) : QObject(parent)
{
tree = pTree;
iterator = new QTreeWidgetItemIterator(tree, QTreeWidgetItemIterator::All);
}

void IplistIterator::finalize(bool result)
{
/* Заморочки с базой и.т.п. будут здесь */
if(result) (**iterator)->setText(1, "OK!");
else (**iterator)->setText(1, "FAIL :(");
++(*iterator);
if(!(**iterator)) { delete iterator; iterator = new QTreeWidgetItemIterator(tree, QTreeWidgetItemIterator::All); }
emit nextPlease((**iterator)->text(0));
}

void IplistIterator::start()
{
emit nextPlease((**iterator)->text(0));
}
Код:
#include "pingthread.h"
#include "iplistiterator.h"
#include "pingstring.h"
#include <QThread>
#include <QTreeWidget>

PingThread::PingThread(QTreeWidget *pTree)
{
tree = pTree;
}

void PingThread::run()
{
PingString *pingString = new PingString;
IplistIterator *iplistIterator = new IplistIterator(tree);

connect(pingString, SIGNAL(pingResult(bool)), iplistIterator, SLOT(finalize(bool)));
connect(iplistIterator, SIGNAL(nextPlease(const QString &)), pingString, SLOT(pingAdress(const QString &)));

iplistIterator->start();
exec();
}

delete mProcess; закомментирован, т.к. по каким-то причинам, если удалять процесс, то крашится программа, даже если перед этим его ->kill()/->terminate()
Ещё, что странно, но объекта в дереве( их пока 2) присваивается результат первого проверенного. Не могу понять почему, по логике ведь всё правильно.
По элементам в дереве бегает всё исправно, даже когда удаляю/добавляю элементы новые. Быстро слишком, но думаю просто передать указатель на родитель в PingString и слипать его в начале pingAdress. Но это всё потом, когда заставлю работать нормально.
Совершенно не понимаю почему всё работает так, будто output не удаляется с первой итерации. Там ведь стоит delete output. Опять я в тупике.
И, как я понимаю, если не удалять процесс, то будет утечка памяти, но почему всё же крашится, если удалять?
Опять прошу более опытных товарищей воздержаться от поучений и отправок в гугл/книгу, я осознаю, что я новичок и знаю мало, поэтому я и здесь. Пробую, пытаюсь разобраться.
« Последнее редактирование: Март 12, 2012, 21:01 от chron1c » Записан
chron1c
Гость
« Ответ #51 : Март 12, 2012, 21:51 »

Разобрался с аутпутом, всё работает корректно, это я опять затупил. Ставил первым адресом на проверку непингущийся, а вторым - пингующийся. Во втором один нолик перепутал Улыбающийся
Вопрос про удаление QProcess остаётся открыт. Так-то всё работает теперь, но утечка памяти образуется.
Записан
mutineer
Гость
« Ответ #52 : Март 12, 2012, 21:55 »

Вопрос про удаление QProcess остаётся открыт. Так-то всё работает теперь, но утечка памяти образуется.

А если делать deleteLater() вместо delete ?
Записан
chron1c
Гость
« Ответ #53 : Март 12, 2012, 22:15 »

То работает, спасибо, не знал о таком слоте. Правда, количество процессов до 205-209 вскакивает, но далее не растёт. Теперь думаю как тормозить итерирование. QProcess в отдельном потоке запускается вроде?
Я пока пытаюсь родителем передавать в итератор указатель на поток, в котором он запускается, а в итераторе потом делать parent()->sleep(3), но не получается так. Почему-то родителем QObject получается у итератора. Это я где-то туплю, пока не понял просто где.

В pingthread:
Код:
IplistIterator *iplistIterator = new IplistIterator(tree, this);

в iplistiterator:
Код:
IplistIterator::IplistIterator(QTreeWidget *pTree, QObject *parent) : QObject(parent)
{
tree = pTree;
iterator = new QTreeWidgetItemIterator(tree, QTreeWidgetItemIterator::All);
}

void IplistIterator::finalize(bool result)
{
/* Заморочки с базой и.т.п. будут здесь */
if(result) (**iterator)->setIcon(0, QPixmap("./Resources/OK.jpg"));
else (**iterator)->setIcon(0, QPixmap("./Resources/notOK.jpg"));
++(*iterator);
if(!(**iterator)) { delete iterator; iterator = new QTreeWidgetItemIterator(tree, QTreeWidgetItemIterator::All); }
parent()->sleep(3);
emit nextPlease((**iterator)->text(0));
}

Сдаётся мне, что-то я о механизме наследования забыл что-то, пойду почитаю.
Записан
mutineer
Гость
« Ответ #54 : Март 12, 2012, 22:20 »

Я пока пытаюсь родителем передавать в итератор указатель на поток, в котором он запускается, а в итераторе потом делать parent()->sleep(3), но не получается так. Почему-то родителем QObject получается у итератора. Это я где-то туплю, пока не понял просто где.

parent() возвращает QObject*. Можешь использовать qobject_cast или dynamic_cast, чтобы привести его к нужному типу
Записан
chron1c
Гость
« Ответ #55 : Март 12, 2012, 22:43 »

Код:
(qobject_cast<PingThread *>(parent()))->sleep(3);
Ругается компилятор, что sleep() - protected-член класса QThread, что так и есть, хех.
Что-то не вспоминается как можно из этого выбраться, разве что придётся слот создавать в pingthread, в нём делать sleep и уже им высылать сигнал запроса следующего элемента.
Записан
chron1c
Гость
« Ответ #56 : Март 12, 2012, 22:50 »

Сделал слот отдельный для приёма, работает, но всё дико тормозит, включая итерфейс. Почему такое может быть?
Код:
#include <QThread>
#include <QTreeWidget>

PingThread::PingThread(QTreeWidget *pTree)
{
tree = pTree;
}

void PingThread::run()
{
PingString *pingString = new PingString;
IplistIterator *iplistIterator = new IplistIterator(tree);

connect(pingString, SIGNAL(pingResult(bool)), iplistIterator, SLOT(finalize(bool)));
connect(iplistIterator, SIGNAL(nextPlease(const QString &)), this, SLOT(checkRequest(const QString &)));
connect(this, SIGNAL(processNext(const QString &)), pingString, SLOT(pingAdress(const QString &)));

iplistIterator->start();
exec();
}

void PingThread::checkRequest(const QString &text)
{
sleep(3);
emit processNext(text);
}
Записан
V1KT0P
Гость
« Ответ #57 : Март 12, 2012, 23:27 »

Сделал слот отдельный для приёма, работает, но всё дико тормозит, включая итерфейс. Почему такое может быть?
После:
PingThread *pingThread = new PingThread;
Делал вот такое:
pingThread->moveToThread(pingThread);
Без этого сигналы работают не совсем так как от них ожидают.
Записан
mutineer
Гость
« Ответ #58 : Март 12, 2012, 23:33 »

После:
PingThread *pingThread = new PingThread;
Делал вот такое:
pingThread->moveToThread(pingThread);
Без этого сигналы работают не совсем так как от них ожидают.

Перемещать объект QThread в тред, которым он управляет, неправильно
Записан
V1KT0P
Гость
« Ответ #59 : Март 12, 2012, 23:40 »

После:
PingThread *pingThread = new PingThread;
Делал вот такое:
pingThread->moveToThread(pingThread);
Без этого сигналы работают не совсем так как от них ожидают.

Перемещать объект QThread в тред, которым он управляет, неправильно
А иначе обработка сигналов будет происходить не в самом потоке, а в том потоке где был создан экземпляр потока. Мало того что это может привести к ошибкам, так если экземпляр был создан в главном потоке то сигналы будут выполняться из главного потока тем самым тормозя графическую часть.
Записан
Страниц: 1 2 3 [4] 5   Вверх
  Печать  
 
Перейти в:  


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