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

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

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

Можно ведь в цикле в потоке написать sleep(<n>), тогда не будет же зря память/процессорное время есть?
Код:
void ProcessTree::run()
{
MyShell *test = new MyShell;
//QTreeWidgetItemIterator iterator(tree, QTreeWidgetItemIterator::All);
(*iterator)->setText(1, "YO!"); //проверка
sleep(3);
test->start(*iterator); //не успевает процесс выполниться, только на половину
run(); //Вот так поток циклится
}
Несколько вопросов возникает:
Когда будет освобождена память, выделенная для MyShell в самом начале? (глупый вопрос, возможно, но я пока в таких делах плохо ориентируюсь ).
Ну и нужно ли делать в конце цикла
Код:
delete test;
или автоматически всё же освободится?

Всё ещё не до конца понял про QThread::run();
Как можно это использовать, чтоб успевал выполниться MyShell и только потом инкрементировался итератор и выполнялся run()?

Каким-то образом нужно ещё хранить итератор этот, чтоб определять его не в run(), а то будет сбрасываться на начало каждый раз. Или лучше циклить всё это через for(;Подмигивающий или аналог?
Извините за, возможно, сумбурное изложение, болею и всё это время сижу над программой, могу на ровном месте уже тупить.
Записан
Bepec
Гость
« Ответ #16 : Март 06, 2012, 15:30 »

Вам бы книжечку почитать Веселый Шлее.

Про сигналы и слоты. Про потоки.

Так же Страуструпика про выделение памяти...

Когда вы sleep(n) делаете, поток у вас засыпаеть намертво. И ему будет до фени все ваши командоссы на n времени Подмигивающий

А если функционал программы расширится, тогда вообще мрак будет Подмигивающий
Записан
chron1c
Гость
« Ответ #17 : Март 06, 2012, 15:40 »

Ну, я знаю, что замирает намертво при sleep(), поэтому и пишу его. Это так, чтоб успеть увидеть изменения.
Шлее как раз открыт сейчас. Просто я подзабыл, освобождается ли память автоматически в Qt Улыбающийся
P.S: раньше у меня не было отдельного класса для процесса, а было всё в потоке определено, но когда запутался, то сделал так, как есть сейчас. Как думаете, имеет ли смысл все сигналы и слоты у потока реализовывать и не использовать свой класс для процесса?
Записан
Bepec
Гость
« Ответ #18 : Март 06, 2012, 15:46 »

Мой ответ - я использую поток как отдельный класс. Проще говоря, поток каждого типа выполняет свои ф-ции. Как бы так оно яснее, наглядней и проще для отладки/реализации.

Конечно же чуть труднее для переноса класса, но... Все операции которые я делаю потоками, НЕ ПОТОКАМИ делать невыгодно Подмигивающий
« Последнее редактирование: Март 06, 2012, 17:44 от Bepec » Записан
neversleep
Гость
« Ответ #19 : Март 06, 2012, 16:46 »

Зато как красиво... Строит глазки
Код
C++ (Qt)
#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
#include <QThread>
 
namespace Ui {
class Dialog;
}
 
class Dialog : public QDialog
{
   Q_OBJECT
 
public:
   explicit Dialog(QWidget *parent = 0);
   ~Dialog();
 
private:
   Ui::Dialog *ui;
 
private slots:
   void pinged(const QString &ip, bool success);
};
 
class Pinger: public QThread
{
   Q_OBJECT
 
public:
   Pinger(QObject *parent = 0):
       QThread(parent)
   {
   }
 
   void ping(const QStringList &ips, const unsigned int timeout);
 
private:
   QStringList addrs;
   unsigned int timeout;
 
protected:
   void run();
 
signals:
   void pinged(const QString &ip, bool success);
};
 
#endif // DIALOG_H
 

Код
C++ (Qt)
#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
 
#ifdef Q_OS_WIN
# include <WinSock2.h>
# include <IPHlpApi.h>
# include <IcmpAPI.h>
#endif
 
#ifdef _MSC_VER
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "iphlpapi.lib")
#endif
 
Dialog::Dialog(QWidget *parent) :
   QDialog(parent),
   ui(new Ui::Dialog)
{
   ui->setupUi(this);
 
   Pinger *pinger = new Pinger;
   connect(pinger, SIGNAL(finished()), pinger, SLOT(deleteLater()));
   connect(pinger, SIGNAL(pinged(QString,bool)), this, SLOT(pinged(QString,bool)));
   pinger->ping(QStringList() << "192.168.0.1" << "192.168.0.5" << "87.118.94.143", 1000);
}
 
Dialog::~Dialog()
{
   delete ui;
}
 
void Dialog::pinged(const QString &ip, bool success)
{
   qDebug() << ip << success;
}
 
void Pinger::ping(const QStringList &ips, const unsigned int timeout)
{
   if (!isRunning()) {
       this->addrs = ips;
       this->timeout = timeout;
 
       start();
   }
}
 
void Pinger::run()
{
#ifdef Q_OS_WIN
   HANDLE hIcmpFile = IcmpCreateFile();
   if (hIcmpFile != INVALID_HANDLE_VALUE) {
       char RequestData[] = "ping";
       DWORD ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(RequestData);
       char *ReplyBuffer = new char[ReplySize];
 
       for (int i = 0, count = addrs.count(); i < count; i++) {
           bool success = false;
           const QString ip = addrs.at(i);
           const int addr = inet_addr(ip.toAscii().data());
           if (addr != INADDR_NONE) {
               if (IcmpSendEcho(hIcmpFile, addr, RequestData, sizeof(RequestData), 0, ReplyBuffer, ReplySize, timeout) != 0) {
                   PICMP_ECHO_REPLY icmpReply = (PICMP_ECHO_REPLY)ReplyBuffer;
                   success = icmpReply->Status == IP_SUCCESS;
               }
           }
 
           emit pinged(ip, success);
       }
       delete []ReplyBuffer;
       IcmpCloseHandle(hIcmpFile);
       exit(0);
   }
#endif
   exit(-1);
}
 
« Последнее редактирование: Март 06, 2012, 18:02 от neversleep » Записан
chron1c
Гость
« Ответ #20 : Март 06, 2012, 17:17 »

Вау, спасибо, но это же WinAPI? Не хочется использовать код, в котором ничего не понимаю Улыбающийся Самому как-то хочется сделать всё.
Из всех моих вопросов ответили только на несколько, жаль.

Может кто-нибудь разъяснить как для дурака?
Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток?

Записан
VozaMFC
Гость
« Ответ #21 : Март 06, 2012, 17:32 »

Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток?
Все таки почитай книгу Шлее о взаимодействии потока с главным посредством сигналов...
Записан
lolbla2
Гость
« Ответ #22 : Март 06, 2012, 19:22 »

Предположим, напишу я в потоке QThread::run(), что случится-то? В каком смысле он будет реагировать только на сигналы и вызовы извне? Или он тогда просто не завершится, пока я в нём самом не напишу exit()? Но если мне нужно в цикле итератор увеличивать и ждать каждый раз, пока выполнится процесс, то, что, мне нужно в главном потоке каждый раз перезапускать этот поток?
Все таки почитай книгу Шлее о взаимодействии потока с главным посредством сигналов...

Отправляют на книжки или на гугл только те, кому лень объяснить человеку, ведь Вы даже не можете себе представить что человеку проще понять Ваши объяснения в пару строчек, чем читать какую-то огромную статью или даже книгу.

P.S. QThread::run() вызывает run класса QThread, которая по умолчанию, определена в классе как:

Код
C++ (Qt)
run()
{
exec() // запускаем  цикл обработки событий, так называемый QEventLoop, то есть класс может принимать сигналы из "внешнего мира"  
}
 


Поправьте если где ошибся
Записан
mutineer
Гость
« Ответ #23 : Март 06, 2012, 20:07 »

Отправляют на книжки или на гугл только те, кому лень объяснить человеку, ведь Вы даже не можете себе представить что человеку проще понять Ваши объяснения в пару строчек, чем читать какую-то огромную статью или даже книгу.

Конечно лень объяснять 50му по счету человеку который не умеет или ленится читать
Записан
neversleep
Гость
« Ответ #24 : Март 06, 2012, 20:57 »

Вау, спасибо, но это же WinAPI? Не хочется использовать код, в котором ничего не понимаю Улыбающийся Самому как-то хочется сделать всё.
Ну да, а использовать чужой процесс куда проще и понятней Улыбающийся Вспомнился один забавный вопрос:
Цитата: управление внешними программами
всем прива
Хотелось бы чтоб моё приложение
1. открыла калькулятор (сделал уже)
2. набрала цыфры (попа ничего не выходит)
3. получив ответ закрыла бы калькулятор(сделал уже)

УЖЕ НАШОЛ ИМИТАЦИЮ КЛАВИШ ЩАС ИМИТАЦИЯ МЫШИ НУЖНА Улыбающийся
http://www.delphimaster.ru/nuts/nuts.html
Записан
Bepec
Гость
« Ответ #25 : Март 06, 2012, 22:29 »

neversleep - как бы ваше предложение интересно, но немного не в тему.

Человек хочет сделать это на Qt, вот и задал вопрос на форуме Qt.
Записан
chron1c
Гость
« Ответ #26 : Март 07, 2012, 02:18 »

Господа, можете мне опять указать, где я облажался?
Шлее прочитал, но всё равно что-то не то.
Код:
#include "processtree.h"
#include <QTreeWidget>
#include <QTreeWidgetItemIterator>
#include <QProcess>

void ProcessTree::run()
{
iterator = new QTreeWidgetItemIterator(tree, QTreeWidgetItemIterator::All);
process = new QProcess;
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(takeOutput()));
connect(this, SIGNAL(pingResult(bool)), this, SLOT(finalize(bool)));
connect(this, SIGNAL(requestNext()), this, SLOT(processNext()));
process->start("cmd /C ping "+(**iterator)->text(0));
exec();
}

void ProcessTree::setTree(QTreeWidget *item)
{
tree = item;
}

void ProcessTree::takeOutput()
{
QString *output = new QString(process->readAllStandardOutput());
process->kill();
if(output->indexOf("TTL") > 0) emit pingResult(true);
else emit pingResult(false);
delete output;
}

void ProcessTree::finalize(bool result)
{
/* Заморочки с базой и.т.п. будут здесь */
if(result) (**iterator)->setText(1, "OK!");
else (**iterator)->setText(1, "FAIL :(");
emit requestNext();
}

void ProcessTree::processNext()
{
if(**iterator){
++(*iterator);
process->start("cmd /C ping "+(**iterator)->text(0));
} else exit(0);
}

Указатель на итератор кажется мне бредом, но каким ещё образом это можно реализовать я пока не знаю.
По логике всё должно работать, но на деле опять всё не так, как хотелось бы.
Хотел бы увидеть дельных ответов с подробными пояснениями где и почему я дурак, и как лучше сделать, а не читай@гугли, буду очень признателен.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Март 07, 2012, 03:44 »

Последний вариант гораздо лучше. Но все равно итератор здесь совсем не к месту. У класса ProcessTree есть четкий вход и выход в виде QString, Кто дает ей вход и кто получает выход - решает тот кто создает экземпляр  класса ProcessTree и управляет им, а не сам класс. Поэтому примерно так

Код
C++ (Qt)
#include "processtree.h"
#include <QProcess>
 
ProcessTree::ProcessTree( void ) :  mProcess(0)
{
}
 
ProcessTree::~ProcessTree( void )
{
delete mProcess;
}
 
// void ProcessTree::run()  // не нужно перекрывать
 
// пришел сигнал от запущенного процесса
void ProcessTree::SlotReadProcess( void )
{
       assert(mProcess);
QString output = mProcess->readAllStandardOutput());
delete mProcess;
       mProcess = 0;
 
       emit SignalReply(reply_Output, output);   // ответили боссу
}
 
// пришла команда (от кто создал экземпляр ProcessTree)
void ProcessTree::SlotCommand( int cmd, QString param )
{
       switch (cmd) {
 
          case cmd_GetStatus:
           if (mProcess) emit SignalReply(reply_Busy, "Waiting for process");
           else emit SignalReply(reply_Ready, "Ready");
           break;
 
          case cmd_RunProcess:
           if (mProcess) emit SignalReply(reply_Busy, "Waiting for process");
           else {
             mProcess = new QProcess();
             connect(mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(slotReadProcess()));
     mProcess->start("cmd /C ping " + param);
             emit SignalReply(reply_Running, "Running");
           }
 
          default:
             emit SignalReply(reply_Error, "Unknown command");
       }
}
 
« Последнее редактирование: Март 07, 2012, 03:51 от Igors » Записан
neversleep
Гость
« Ответ #28 : Март 07, 2012, 05:07 »

neversleep - как бы ваше предложение интересно, но немного не в тему.

Человек хочет сделать это на Qt, вот и задал вопрос на форуме Qt.
Я как бы не навязываюсь, и если мой подход идёт вразрез с Qt`шным, то ваша правда, давайте и дальше компенсировать недостатки фреймворка чужими программами.
Записан
Bepec
Гость
« Ответ #29 : Март 07, 2012, 06:54 »

neversleep, Человек просто не умеет пока обращаться с потоками. Таки дадим ему возможность научиться???

Причём потоки Qt не являются недостатком. А скорее просто - одним из инструментов, которым надо овладеть. Как и другие ему аналогичные потоки.(boost например)
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


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