Название: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 01:21 Доброго времени суток.
Собственно, проблема: Есть класс для процесса и для потока. Класс потока: Код: //========== processtree.h Через setTree принимает указатель на QtreeWidget, в своей переменной запоминает его. Далее создаётся итератор и в процесс передаётся указатель на QTreeWidgetItem. Итератор создаю, т.к. потом планирую по очереди каждый QTreeWidgetItem в tree перебрать. ( вообще, нужно проверить пингуется ли комп, айпишник которого лежит в text(0) в каждом QTreeWidgetItem. Класс процесса: Код: //=========== H По каким-то причинам процесс не высылает readyReadStandardOutput(), ну или его не получает slotDataOnStdout(). Пробовал в главном потоке процесс создавать и родителем его делать QWidget, а не QProcess ( в примере, по которому учился он был с ГУИ и с родителем QWidget ), но тогда придётся заморачиваться с сигналами и слотами между потоками, да и вообще мне как-то сложно представить как тогда задачу свою решить. Может, можно и как-нибудь иначе сделать то, что мне нужно, но с Qt я работаю буквально пару дней, так что, естественно, многого не знаю. Название: Re: Процесс внутри потока? Отправлено: neversleep от Март 06, 2012, 05:33 Зачем вообще парится с процессом? Юзай винапи ф-цию IcmpSendEcho (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366050%28v=vs.85%29.aspx) или т.н raw sockets.
Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 11:57 Я в этом понимаю ещё меньше, чем в Qt, т.е. вообще ничего :)
По ТЗ нужно сделать именно на Qt, да и уже просто интересно почему в моём случае не работает. Столько провозился и времени столько потерял, что теперь, не разобравшись, забивать как-то не хочется. Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 12:02 минимально компилируемый проект в архив и в студию.
Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 12:57 Комментарии внутри.
Чуть не забыл, пишу его в VS2008 с Add-In'ом Qt4.6. Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 13:21 Отвечаю - интересная реализация конечно потоков...
Первое Тебя не насторожили надписи в Output Код: QObject: Cannot create children for a parent that is in a different thread. Которые вылетают на строчке Код: m_process->start("cmd /C ping "+item->text(0)); Мораль - ты создаёшь QProcess в 1 потоке, а потом пытаешься запустить во втором...Он и сопротивляется. Второе Очень интересная реализация потоков. Код: void ProcessTree::run() А по делу - читай про потоки, делай простенькие программки. Они тебе не будут терпеливо ждать, пока придёт ответ, выполнится QProcess. Он до конца run дойдёт и на кладбище. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 13:43 На самом деле я даже не знаю как в этот Output заглянуть. С VS столько же, сколько и с Qt знаком. Раньше в блокноте писал всё.
Передавать адрес процесса я только сейчас стал, до этого было в ProcessTree: Код: MyShell *test = new MyShell; После Код: process->start(*iterator); Код: sleep(2); Как-то ведь можно поток заставить ждать пока не придёт сигнал от процесса? Так думал поступить. Ну и как в комментариях написал, то в теле run() хотел ставить бесконечный цикл, просто сейчас его там нет, т.к. на одном элементе даже не работает схема. Интересная реализация, если с профессиональной точки зрения, то это, скорее, в плохом или хорошем смысле? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 13:55 Я бы сказал честно - в отвратительном :)
Понамешано всего(хотя понятно, новичок всё же). А ты не пробовал к примеру создавать QProcess динамически внутри потока. И до тех пор, пока поток не обработает все NNN адресов, его не отпускать на кладбище? Набросок на мой (возможно не оч профессиональный) взгляд: Создаётся виджет, заполняется таблица с IP. После чего тыкается кнопка и запускается поток. Поток каждый раз создаёт QProcess, ждёт его завершения и результатов, переходит к следующему. Как только адреса заканчиваются - заканчивается цикл и поток умирает. До тех пор, пока кто-то добрый не нажмёт кнопочку и снова не создаст экземпляр потока. PS программа на 8,000-12,000 строк в блокноте, это, конечно, сильно. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 14:00 Ну я именно так и хочу сделать. Процесс оказался в главном потоке только потому, что я проверял, будет ли хоть так работать. Как и выше написал, сейчас у меня так:
Код: void ProcessTree::run() Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 14:09 ну вызови ты в конце концов QThread::run();
Код: void ProcessTree::run() Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 14:46 О мой бог, как же я затупил. Спасибо!
Только сейчас дошло, что поток, завершившись, убивает и процесс, который просто не успевает завершиться. Как я понимаю, поставив в конец run() - я зациклю поток. Но как заставить его перебирать итераторы? Хм. Почитал в ассистенте про QThread::run(), так и не понял, почему, поставив его в конец, всё заработало. У родителя( QThread ) не переопределён у меня же run(), => вызовется QThread::exec()? В доках написано, что он буде ждать, пока не получит exit(), но от кого он будет его ждать? И когда будет выслан exit()? Когда завершится процесс внутри ProcessTree? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 14:54 QThread::run() делает поток "событийным", реагирующим только на вызовы извне и сигналы. Сам же он ждёт тихо тихо.
А exit() ему надо передавать самому(я так делаю, ибо потоки у меня опасные ;) ). Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки. (Дурью маяться тяжелооо... Вот и будет йхенй страдать ;) ) ПОПРАВКА - зациклить на пустой цикл аля Код: while(true) Название: Re: Процесс внутри потока? Отправлено: BRE от Март 06, 2012, 15:08 Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки. ;D Ты откуда это берешь? Почему он будет память жрать? Название: Re: Процесс внутри потока? Отправлено: LisandreL от Март 06, 2012, 15:08 Если же не вызывать run(), а зациклить на пустой цикл, то поток будет жрать память не по деццки. (Дурью маяться тяжелооо... Вот и будет йхенй страдать Память? С чего бы ему память-то потреблять? У вас она течёт где-то?Может вы загрузку процессора имели в виду? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 15:12 вру вру ) Процессорное время ;)
Точнее даже не всего процессора, а 1 ядро ;) Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 15:22 Можно ведь в цикле в потоке написать sleep(<n>), тогда не будет же зря память/процессорное время есть?
Код: void ProcessTree::run() Когда будет освобождена память, выделенная для MyShell в самом начале? (глупый вопрос, возможно, но я пока в таких делах плохо ориентируюсь ). Ну и нужно ли делать в конце цикла Код: delete test; Всё ещё не до конца понял про QThread::run(); Как можно это использовать, чтоб успевал выполниться MyShell и только потом инкрементировался итератор и выполнялся run()? Каким-то образом нужно ещё хранить итератор этот, чтоб определять его не в run(), а то будет сбрасываться на начало каждый раз. Или лучше циклить всё это через for(;;) или аналог? Извините за, возможно, сумбурное изложение, болею и всё это время сижу над программой, могу на ровном месте уже тупить. Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 15:30 Вам бы книжечку почитать :D Шлее.
Про сигналы и слоты. Про потоки. Так же Страуструпика про выделение памяти... Когда вы sleep(n) делаете, поток у вас засыпаеть намертво. И ему будет до фени все ваши командоссы на n времени ;) А если функционал программы расширится, тогда вообще мрак будет ;) Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 15:40 Ну, я знаю, что замирает намертво при sleep(), поэтому и пишу его. Это так, чтоб успеть увидеть изменения.
Шлее как раз открыт сейчас. Просто я подзабыл, освобождается ли память автоматически в Qt :) P.S: раньше у меня не было отдельного класса для процесса, а было всё в потоке определено, но когда запутался, то сделал так, как есть сейчас. Как думаете, имеет ли смысл все сигналы и слоты у потока реализовывать и не использовать свой класс для процесса? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 15:46 Мой ответ - я использую поток как отдельный класс. Проще говоря, поток каждого типа выполняет свои ф-ции. Как бы так оно яснее, наглядней и проще для отладки/реализации.
Конечно же чуть труднее для переноса класса, но... Все операции которые я делаю потоками, НЕ ПОТОКАМИ делать невыгодно ;) Название: Re: Процесс внутри потока? Отправлено: neversleep от Март 06, 2012, 16:46 Зато как красиво... ::)
Код
Код
Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 06, 2012, 17:17 Вау, спасибо, но это же WinAPI? Не хочется использовать код, в котором ничего не понимаю :) Самому как-то хочется сделать всё.
Из всех моих вопросов ответили только на несколько, жаль. Может кто-нибудь разъяснить как для дурака? Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток? Название: Re: Процесс внутри потока? Отправлено: VozaMFC от Март 06, 2012, 17:32 Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток? Все таки почитай книгу Шлее о взаимодействии потока с главным посредством сигналов...Название: Re: Процесс внутри потока? Отправлено: lolbla2 от Март 06, 2012, 19:22 Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток? Все таки почитай книгу Шлее о взаимодействии потока с главным посредством сигналов...Отправляют на книжки или на гугл только те, кому лень объяснить человеку, ведь Вы даже не можете себе представить что человеку проще понять Ваши объяснения в пару строчек, чем читать какую-то огромную статью или даже книгу. P.S. QThread::run() вызывает run класса QThread, которая по умолчанию, определена в классе как: Код
Поправьте если где ошибся Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 06, 2012, 20:07 Отправляют на книжки или на гугл только те, кому лень объяснить человеку, ведь Вы даже не можете себе представить что человеку проще понять Ваши объяснения в пару строчек, чем читать какую-то огромную статью или даже книгу. Конечно лень объяснять 50му по счету человеку который не умеет или ленится читать Название: Re: Процесс внутри потока? Отправлено: neversleep от Март 06, 2012, 20:57 Вау, спасибо, но это же WinAPI? Не хочется использовать код, в котором ничего не понимаю :) Самому как-то хочется сделать всё. Ну да, а использовать чужой процесс куда проще и понятней :) Вспомнился один забавный вопрос:Цитата: управление внешними программами всем прива http://www.delphimaster.ru/nuts/nuts.htmlХотелось бы чтоб моё приложение 1. открыла калькулятор (сделал уже) 2. набрала цыфры (попа ничего не выходит) 3. получив ответ закрыла бы калькулятор(сделал уже) УЖЕ НАШОЛ ИМИТАЦИЮ КЛАВИШ ЩАС ИМИТАЦИЯ МЫШИ НУЖНА :) Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 06, 2012, 22:29 neversleep - как бы ваше предложение интересно, но немного не в тему.
Человек хочет сделать это на Qt, вот и задал вопрос на форуме Qt. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 02:18 Господа, можете мне опять указать, где я облажался?
Шлее прочитал, но всё равно что-то не то. Код: #include "processtree.h" Указатель на итератор кажется мне бредом, но каким ещё образом это можно реализовать я пока не знаю. По логике всё должно работать, но на деле опять всё не так, как хотелось бы. Хотел бы увидеть дельных ответов с подробными пояснениями где и почему я дурак, и как лучше сделать, а не читай@гугли, буду очень признателен. Название: Re: Процесс внутри потока? Отправлено: Igors от Март 07, 2012, 03:44 Последний вариант гораздо лучше. Но все равно итератор здесь совсем не к месту. У класса ProcessTree есть четкий вход и выход в виде QString, Кто дает ей вход и кто получает выход - решает тот кто создает экземпляр класса ProcessTree и управляет им, а не сам класс. Поэтому примерно так
Код
Название: Re: Процесс внутри потока? Отправлено: neversleep от Март 07, 2012, 05:07 neversleep - как бы ваше предложение интересно, но немного не в тему. Я как бы не навязываюсь, и если мой подход идёт вразрез с Qt`шным, то ваша правда, давайте и дальше компенсировать недостатки фреймворка чужими программами.Человек хочет сделать это на Qt, вот и задал вопрос на форуме Qt. Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 07, 2012, 06:54 neversleep, Человек просто не умеет пока обращаться с потоками. Таки дадим ему возможность научиться???
Причём потоки Qt не являются недостатком. А скорее просто - одним из инструментов, которым надо овладеть. Как и другие ему аналогичные потоки.(boost например) Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 11:58 Последний вариант гораздо лучше. Но все равно итератор здесь совсем не к месту. У класса ProcessTree есть четкий вход и выход в виде QString, Кто дает ей вход и кто получает выход - решает тот кто создает экземпляр класса ProcessTree и управляет им, а не сам класс. Поэтому примерно так Код
Вот, как раз то, что хотел увидеть, спасибо! :) Получается, что при Код: delete mProcess; Итератор я использовал т.к. не знал как ещё обращаться к элементам в QTreeWidget. Получается, что такой экземпляр ProcessTree мне нужно в своём потоке ( в его run() ) создать, соеденить его SignalReply с каким-то слотом в потоке, а в конце прописать exec()? И в потоке мне нужно будет ловить сигнал SignalReply и, если получен output, то проверять его на "TTL"/менять текст по итератору/высылать команду в SlotCommand, чтоб создавался новый процесс? Хм. Всё равно придётся передавать в поток дерево, например, а чтоб его в потоке постоянно прогонять нужен какой-то цикл, что ли. Или можно зациклить сигналами и слотами просто? ( пытался же, но не получилось ). И опять же, в потоке только итератором мне видится возможным это провернуть. И ещё есть один вопрос, который мне с трудом дал уснуть сегодня, когда я по указателю соединяю процесс со слотом, то, убив/удалив процесс, а указателю присвоив адрес нового процесаа, будет ли новый процесс соединён так же? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 07, 2012, 12:00 Если у тебя есть указатель на дерево в потоке, то ты можешь делать с деревом всё, что пожелаешь. От убиения дерева, до постройки из него домика.
Насчёт вопроса с сигналом я неуверен, но помоему не будет соединён. Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 07, 2012, 12:04 И ещё есть один вопрос, который мне с трудом дал уснуть сегодня, когда я по указателю соединяю процесс со слотом, то, убив/удалив процесс, а указателю присвоив адрес нового процесаа, будет ли новый процесс соединён так же? Без повторного connect не будет Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 12:11 У меня просто в дереве у некоторых айтемов есть дети, т.е. уже внуки дерева, и я так и не нашел в доках ( или плохо искал ) как можно поочереди обращаться ко всем QTreeWidgetItem, кроме как через итератор. Приходилось во внутренних переменных хранить адрес на итератор(sic!), чтоб он был в потоке виден не только в run();
Как-то пробовал в QObjectList дёргать детей по findChildren<QTreeWidgetItem *>();, но как-то не очень решением мне это показалось. Или как вариант? Название: Re: Процесс внутри потока? Отправлено: Bepec от Март 07, 2012, 12:12 Создай в потоке указатель на итератор твой. И потом уже используй-используй-используй.
Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 07, 2012, 12:16 Создай в потоке указатель на итератор твой. И потом уже используй-используй-используй. Указатель на итератор? а если итератор инвалидируется или уничтожится? Или дерево не меняется? Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 12:23 Дерево не меняется, меняются только элементы в нём. Думал, когда итератор будет уже ни на что не показывать, то пересоздавать его, на начало дерева возвращая этим.
Хм, но у меня и был в потоке указатель на итератор. Казалось мне каким-то странным делать так: Код: (**iterator)->setText(0, "o.o"); Хм. А когда создаётся итератор, то ему как бы присваивается список возможных значений или как? Просто вот, например, инициализировал я итератор. В конце дерева есть последний элемент, предположим. Итератор до него ещё не добрался, а элемент я удалил и добавил в конец уже новый. Перейдёт ли итератор корректно на него? Название: Re: Процесс внутри потока? Отправлено: BRE от Март 07, 2012, 12:32 Не нужно передавать в поток никакие итераторы, тем более на элементы связанные с GUI. Чем меньше поток будет знать, тем лучше.
Что ему знать необходимо? - адрес хоста для пингования. Все. Вот и передавай ему этот адрес в строке, а он должен вернуть ответ: пингуется или нет. Не нужно все пытаться засунуть в один поток. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 12:38 Хм, ок. Но тогда мне в ГУИ потоке нужно будет этим же итератором перебивать в цикле все элементы, высылая по одному в тот поток? Гуи-то не повиснет, можно событиям давать отправляться каждую итерацию, но вот как тогда менять информацию, принадлежащую пингующемуся/не пингующемуся адресу в дереве? Как-то заморачиваться со слотом в главном потоке, в котором нужно будет ещё и к элементу дерева обращаться и следить ещё как-то, чтоб цикл основном не "убежал вперёд", разве комильфо?
Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 07, 2012, 12:57 Дерево не меняется, меняются только элементы в нём. .... В конце дерева есть последний элемент, предположим. Итератор до него ещё не добрался, а элемент я удалил и добавил в конец уже новый. Так меняется дерево или нет? в одном ответе две противоречивых фразы Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 07, 2012, 13:13 Я думал другое имелось ввиду. Сам объект дерева тем же остаётся, а меняются в нём элементы. Только одно дерево будет проверяться.
Название: Re: Процесс внутри потока? Отправлено: Igors от Март 07, 2012, 16:05 Получается, что при Вроде в букваре написано что даКод: delete mProcess; И ещё есть один вопрос, который мне с трудом дал уснуть сегодня, когда я по указателю соединяю процесс со слотом, то, убив/удалив процесс, а указателю присвоив адрес нового процесаа, будет ли новый процесс соединён так же? Нет, не будет, нужно опять соединятьИтератор я использовал т.к. не знал как ещё обращаться к элементам в QTreeWidget. Создаете ProcessTree один раз напр на старте приложения и удаляете его напр на финише. Если надо обойти дерево, то лучше поручить эту задачу др классу. Можно унаследоваться от QTreeWidgetItemIterator, напрПолучается, что такой экземпляр ProcessTree мне нужно в своём потоке ( в его run() ) создать, соеденить его SignalReply с каким-то слотом в потоке, а в конце прописать exec()? И в потоке мне нужно будет ловить сигнал SignalReply и, если получен output, то проверять его на "TTL"/менять текст по итератору/высылать команду в SlotCommand, чтоб создавался новый процесс? Хм. Всё равно придётся передавать в поток дерево, например, а чтоб его в потоке постоянно прогонять нужен какой-то цикл, что ли. Или можно зациклить сигналами и слотами просто? ( пытался же, но не получилось ). И опять же, в потоке только итератором мне видится возможным это провернуть. Код Этот класс спокойно создаете хоть бы и в главной нитке. По SlotReply обновляете UI, в конце-концов получите SignalFinished. По поводу "зациклить" - в событийной (event-driven) схеме этого нет. Неизвестно сколько времени займет хотя бы запуск процесса, поэтому в любом случае надо выставить значения каких-то переменных и ждать сигнала, продолжая работу с UI и др Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 10, 2012, 00:24 Хм, понятно. Т.е. лучше заставить в доп. потоке висеть процесс и по сигналу запускать и давать вывод, а обрабатывать его уже в главном. Хм, ок, попробую. Хотя с трудом представляется как всё это реализовать. А чем плоха моя идея засунуть вообще всю обработку в доп. поток? Там что-то принципиально не верно, что ли? Я её уже по-всякому мучил, так и не заставил работать.
Попробую сделать как советовал Igors. Нопочему-то не объявляется класс, унаследованный от итератора. Хоть я и хочу спать, но раз 5 пересмотрел - вроде всё верно ведь пишу. Код: #ifndef TEST_H Компилятор выдаёт: Код: 1>c:\qtsdk\myprojects\myapplication\myapplication\generatedfiles\debug\../../test.h(11) : error C2143: syntax error : missing ';' before 'public' Пробовал включать QObject туда, тогда получаю: Код: 1>.\GeneratedFiles\Debug\moc_test.cpp(51) : error C2039: 'staticMetaObject' : is not a member of 'QTreeWidgetItemIterator' В данный момент вникаю в вывод компилятора. Подозреваю, что итератор нельзя наследовать вообще. Название: Re: Процесс внутри потока? Отправлено: BRE от Март 10, 2012, 08:48 Итератор это небольшой инструментальный класс, объекты которого, позволяют выполнять навигацию по контейнеру. Все. Пытаться запихнуть туда еще "кучу важных дел" глупо. Это как к строительному мастерку прикрутить метровый уровень - получиться новый инструмент, только делать с ним уже ничего не захочется. :)
Я бы использовал пул потоков + очередь, для хранения адресов хостов (темы где есть работающие примеры на форуме есть), но если хочешь через сигналы-слоты, то сделай класс-менеджер заданий наследником QObject, а уже внутри используй QTreeWidgetItemIterator. И да, самое простое решение это воспользоваться QtConcurrent. Можно все сделать в несколько строк. Название: Re: Процесс внутри потока? Отправлено: Igors от Март 10, 2012, 13:04 А чем плоха моя идея засунуть вообще всю обработку в доп. поток? Там что-то принципиально не верно, что ли? Смотрите какие есть связки/зависимости. Запуск процесса у Вас связан с итератором дерева. Эта конструкция не имеет никакой гибкости. Потребуется обойти напр таблицу - и что, весь запуск процесса опять писать? Также передача данных (асинхронка) в нитку обходится гораздо дороже - и по написанию, и по времени выполнения. Всегда лучше вынести из нитки все что можно.Попробую сделать как советовал Igors. Ну с наследованием я переборщил - наследование от итератора + QObject явно "не то". Так передайте итератор по ссылке Нопочему-то не объявляется класс, унаследованный от итератора. Код "альтернатива наследование/членство" Итератор это небольшой инструментальный класс, объекты которого, позволяют выполнять навигацию по контейнеру. Все. Пытаться запихнуть туда еще "кучу важных дел" глупо. Это как к строительному мастерку прикрутить метровый уровень - получиться новый инструмент, только делать с ним уже ничего не захочется. :) Операция может быть и сложной, но если она применяется только к элементу - по смыслу это итерирование. Но согласен, раздувать класс итератора ни к чему.Я бы использовал пул потоков + очередь, для хранения адресов хостов (темы где есть работающие примеры на форуме есть), но если хочешь через сигналы-слоты, то сделай класс-менеджер заданий наследником QObject, а уже внутри используй QTreeWidgetItemIterator. Не уверен насчет QtConcurrent, как я понял, процесс должен запускаться снова по окончанию предыдущего - нужно последовательное, а не параллельное выполнение. Через очередь - это уже др задача/функционал. Разница видна напр если дерево меняется динамически (пока идет опрос адресов)И да, самое простое решение это воспользоваться QtConcurrent. Можно все сделать в несколько строк. Название: Re: Процесс внутри потока? Отправлено: BRE от Март 10, 2012, 13:10 процесс должен запускаться снова по окончанию предыдущего Можно легко перезапускать.нужно последовательное, а не параллельное выполнение. Что-то мне подсказывает что это не так. Для чего тогда использовать потоки?Название: Re: Процесс внутри потока? Отправлено: Igors от Март 10, 2012, 13:23 нужно последовательное, а не параллельное выполнение. Что-то мне подсказывает что это не так. Для чего тогда использовать потоки?Название: Re: Процесс внутри потока? Отправлено: BRE от Март 10, 2012, 13:32 Ну это вопрос к chron1c :) Согласен. :)Я понял что опрос адресов выполнять в отдельной нитке - чтобы UI не замерзало, разумно. Ну как бы QProcess прекрасно работает асинхронно, совсем не замораживая UI.Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 10, 2012, 23:06 Дело не только в QProcess, нужно постоянно работать с элементами дерева, один за другим. И элементы будут удаляться/изменяться/добавляться. К тому же, далее планируется расширение программы ещё одним функционалом, поэтому в главном потоке хочется оставить минимум.
Гибкость, хм. Да, соглашусь с вами, хоть она мне тут и не нужна, но лишней не будет. Сделаю чтоб класс принимал QString. В идеале, сделать бы в потоке просто цикл бесконечный, который продолжался бы переходил на следующую итерацию только после того как получит сигнал определённый. А когда итератор бы начинал указывать ни на что, то просто его пересоздавать, заставляя тем самым указывать на начало дерева снова. Сделать "бесконечный цикл" только сигналами и слотами представляется мне нереализуемым, т.к. сколько бы я не пытался, даже если по логике всё корректно, то не работало ничего. Название: Re: Процесс внутри потока? Отправлено: Igors от Март 11, 2012, 10:36 В идеале, сделать бы в потоке просто цикл бесконечный, который продолжался бы переходил на следующую итерацию только после того как получит сигнал определённый. А когда итератор бы начинал указывать ни на что, то просто его пересоздавать, заставляя тем самым указывать на начало дерева снова. Тогда передавайте во второй класс указатель на дерево а итератор делайте членом этого класса. В слоте SlotRеply присваиваете ему новый итератор как только старый закончился. Сделав второй маленький класс мы развязали себе руки, его легко менять как угодно, в этом гибкость.Сделать "бесконечный цикл" только сигналами и слотами представляется мне нереализуемым, т.к. сколько бы я не пытался, даже если по логике всё корректно, то не работало ничего. Все прекрасно получается если "бесконечный цикл" заменить на "бесконечный обмен сигналами" :)..в главном потоке хочется оставить минимум. Это желание понятно, но не следует претворять его в жизнь буквально, типа "больше кода/логики должно быть перенесено в др нитки"Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 12, 2012, 20:38 Хм. Попробовал так:
Код: #include "pingstring.h" Код: #include "iplistiterator.h" Код: #include "pingthread.h" delete mProcess; закомментирован, т.к. по каким-то причинам, если удалять процесс, то крашится программа, даже если перед этим его ->kill()/->terminate() Ещё, что странно, но объекта в дереве( их пока 2) присваивается результат первого проверенного. Не могу понять почему, по логике ведь всё правильно. По элементам в дереве бегает всё исправно, даже когда удаляю/добавляю элементы новые. Быстро слишком, но думаю просто передать указатель на родитель в PingString и слипать его в начале pingAdress. Но это всё потом, когда заставлю работать нормально. Совершенно не понимаю почему всё работает так, будто output не удаляется с первой итерации. Там ведь стоит delete output. Опять я в тупике. И, как я понимаю, если не удалять процесс, то будет утечка памяти, но почему всё же крашится, если удалять? Опять прошу более опытных товарищей воздержаться от поучений и отправок в гугл/книгу, я осознаю, что я новичок и знаю мало, поэтому я и здесь. Пробую, пытаюсь разобраться. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 12, 2012, 21:51 Разобрался с аутпутом, всё работает корректно, это я опять затупил. Ставил первым адресом на проверку непингущийся, а вторым - пингующийся. Во втором один нолик перепутал :)
Вопрос про удаление QProcess остаётся открыт. Так-то всё работает теперь, но утечка памяти образуется. Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 12, 2012, 21:55 Вопрос про удаление QProcess остаётся открыт. Так-то всё работает теперь, но утечка памяти образуется. А если делать deleteLater() вместо delete ? Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 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) Сдаётся мне, что-то я о механизме наследования забыл что-то, пойду почитаю. Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 12, 2012, 22:20 Я пока пытаюсь родителем передавать в итератор указатель на поток, в котором он запускается, а в итераторе потом делать parent()->sleep(3), но не получается так. Почему-то родителем QObject получается у итератора. Это я где-то туплю, пока не понял просто где. parent() возвращает QObject*. Можешь использовать qobject_cast или dynamic_cast, чтобы привести его к нужному типу Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 12, 2012, 22:43 Код: (qobject_cast<PingThread *>(parent()))->sleep(3); Что-то не вспоминается как можно из этого выбраться, разве что придётся слот создавать в pingthread, в нём делать sleep и уже им высылать сигнал запроса следующего элемента. Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 12, 2012, 22:50 Сделал слот отдельный для приёма, работает, но всё дико тормозит, включая итерфейс. Почему такое может быть?
Код: #include <QThread> Название: Re: Процесс внутри потока? Отправлено: V1KT0P от Март 12, 2012, 23:27 Сделал слот отдельный для приёма, работает, но всё дико тормозит, включая итерфейс. Почему такое может быть? После:PingThread *pingThread = new PingThread; Делал вот такое: pingThread->moveToThread(pingThread); Без этого сигналы работают не совсем так как от них ожидают. Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 12, 2012, 23:33 После: PingThread *pingThread = new PingThread; Делал вот такое: pingThread->moveToThread(pingThread); Без этого сигналы работают не совсем так как от них ожидают. Перемещать объект QThread в тред, которым он управляет, неправильно Название: Re: Процесс внутри потока? Отправлено: V1KT0P от Март 12, 2012, 23:40 После: PingThread *pingThread = new PingThread; Делал вот такое: pingThread->moveToThread(pingThread); Без этого сигналы работают не совсем так как от них ожидают. Перемещать объект QThread в тред, которым он управляет, неправильно Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 12, 2012, 23:43 Значит нужно выносить рабочую часть из наследника QThread в отдельный класс и мувать его в обычный QThread
http://habrahabr.ru/blogs/qt_software/115830/ http://habrahabr.ru/blogs/qt_software/115835/ http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ Название: Re: Процесс внутри потока? Отправлено: V1KT0P от Март 12, 2012, 23:53 Значит нужно выносить рабочую часть из наследника QThread в отдельный класс и мувать его в обычный QThread Согласен, но как временное решение мувать самого в себя подойдет. Вот еще бы пример в справке показывал бы как надо правильно делать. Ибо я думаю многие об это спотыкаются.http://habrahabr.ru/blogs/qt_software/115830/ http://habrahabr.ru/blogs/qt_software/115835/ http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 13, 2012, 00:07 Значит нужно выносить рабочую часть из наследника QThread в отдельный класс и мувать его в обычный QThread Согласен, но как временное решение мувать самого в себя подойдет. Вот еще бы пример в справке показывал бы как надо правильно делать. Ибо я думаю многие об это спотыкаются.http://habrahabr.ru/blogs/qt_software/115830/ http://habrahabr.ru/blogs/qt_software/115835/ http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ "Нет ничего более постоянного, чем временное" - очень правильная поговорка, так что даже как временное я бы не делал. Ведь вынести все из одного класса в другой очень несложно Название: Re: Процесс внутри потока? Отправлено: mutineer от Март 13, 2012, 00:11 Сделал слот отдельный для приёма, работает, но всё дико тормозит, включая итерфейс. Почему такое может быть? потому что sleep() вызвается в главном потоке ибо объект-наследник QThread живет в главном потоке и его слоты работают в нем (при автоконнекте). соответсвенно тормозишь ты главный поток как вариант может помочь такое (если я правильно понял код): Код: connect(iplistIterator, SIGNAL(nextPlease(const QString &)), this, SLOT(checkRequest(const QString &)), Qt::DirectConnection); Название: Re: Процесс внутри потока? Отправлено: Igors от Март 13, 2012, 12:40 И, как я понимаю, если не удалять процесс, то будет утечка памяти, но почему всё же крашится, если удалять? Не мешает посмотреть что пишет консоль. И вообще попечатать QThread::currentThreadId (где кто выполняется). Обычно выясняется много интересногоОпять прошу более опытных товарищей воздержаться от поучений и отправок в гугл/книгу, Трудно воздержаться от назидательных фраз :) Товарищи говорили - чем меньше логики в нитке - тем лучше. Но Вы опять втулили итератор в нитку. Результат void IplistIterator::finalize(bool result) А из какой нитки Вы дергаете UI? (можно только из главной){ /* Заморочки с базой и.т.п. будут здесь */ if(result) (**iterator)->setText(1, "OK!"); else (**iterator)->setText(1, "FAIL :("); Название: Re: Процесс внутри потока? Отправлено: chron1c от Март 20, 2012, 09:16 С задачей разобрался, процесс перестал создавать/удалять, использую ->kill(), а потом ->start() для другого IP.
Решил вообще не использовать поток отдельный, а проверять айпи и переходить к следующему по timeOut у QTimer'а. Спасибо всем за помощь :) Возникла другая проблема теперь, но отдельную тему создавать не хочется для этого. В классах своих создавал графические элементы динамически, а сейчас переделал и создал .ui для каждого класса. По каким-то причинам не работает show() с объектом класса, для которого задан .ui. Нужно внутри класса, из слота его, вызывать show(), пробовал и open() и this->show()/open(), даже извне пробовал show() вызывать - всё равно не отображается. В чём может быть причина? В гугле ничего найти не удалось. Сам объект(хотя так во всех объектах, переделанных с помощью добавления GUI-класса). Код: // ========== h |