Russian Qt Forum

Qt => Общие вопросы => Тема начата: a_n_y_a от Июль 28, 2009, 08:32



Название: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Июль 28, 2009, 08:32
 Каким образом запустить процесс в виде функции. Или может быть это поток? Есть диалог, при нажатии на кнопку запускается процесс в котором выполняется заданная функция. Диалог ждет окончания работы этого процесса и завершает прогрмму. Как это сделать в Qt?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: Авварон от Июль 28, 2009, 08:37
тебе надо унаследоваться от класса QThread и переопределить метод run(). В теории можно добавить член - указатель на функцию и сеттер ее и из своего run() вызывать. Вопрос в том, получится ли передавать методы других классов... когда я разбирался с указателями на методы классов, синтаксис был страшненький (особенно вызова)


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: pastor от Июль 28, 2009, 09:18
См. QtConcurrent::run и QtConcurrent Run Function Example


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: ритт от Июль 28, 2009, 15:02
или QThreadPool и QRunnable


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 06, 2009, 09:51
тебе надо унаследоваться от класса QThread и переопределить метод run(). В теории можно добавить член - указатель на функцию и сеттер ее и из своего run() вызывать. Вопрос в том, получится ли передавать методы других классов... когда я разбирался с указателями на методы классов, синтаксис был страшненький (особенно вызова)

Спасибо, сделал, но есть проблемы:
Есть поток QThread, в него передается указатель на диалог,
Potok::Potok(QWidget *parent)
    : QWidget(parent)
{
...
   Pt=new PotokThread(this);
...
}

и в потоке запускается цикл:
   for(i=100;i>0;i--)
   {
      msleep(100);
//      Здесь Parent - укзатель на диалог,
//      ui.Zapolnenie - указатель на прогресбар в диалоге.
      Parent->ui.Zapolnenie->setValue(i);
   };
Прогрессбар заполняется нормально, но появляются сообщения на
каждое обращение к прогрессбару:

X Error: RenderBadGlyphSet (invalid GlyphSet parameter) 184
  Extension:    155 (RENDER)
  Minor opcode: 25 (RenderCompositeGlyphs32)
  Resource id:  0x0

Что я сделал не правильно.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: BRE от Август 06, 2009, 10:13
Миллион раз уже обсуждали... :(
Нельзя работать с GUI из другого потока.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 06, 2009, 12:13
Миллион раз уже обсуждали... :(
Нельзя работать с GUI из другого потока.

Но в виндах (в VC++) все работает нормально. Может как нибудь можно?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: BRE от Август 06, 2009, 12:23
Миллион раз уже обсуждали... :(
Нельзя работать с GUI из другого потока.

Но в виндах (в VC++) все работает нормально. Может как нибудь можно?
Нигде нельзя.  ;)
Поищи по форуму, есть много тем где это обсуждалось.
Из дочерней нити ты можешь послать сигнал или событие в главную (GUI) нить и в контексте главной нити работать с GUI объектами как захочешь.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 07, 2009, 08:56
Миллион раз уже обсуждали... :(
Нельзя работать с GUI из другого потока.

Но в виндах (в VC++) все работает нормально. Может как нибудь можно?
Нигде нельзя.  ;)
Поищи по форуму, есть много тем где это обсуждалось.
Из дочерней нити ты можешь послать сигнал или событие в главную (GUI) нить и в контексте главной нити работать с GUI объектами как захочешь.

Спасибо все нашел. Вот только что то у меня возникли неожиданные проблемы.
Что то у меня не транслируется, что я делаю не правильно?
Есть класс:
class PotokThread : public QThread
{
   Q_OBJECT

public:
   PotokThread(){};
   virtual void run ();
   int I;
signals:
   void valueChanged(int i);
};

Говорит:
debug/potok.o: In function `PotokThread':
/usr/Potok/Potok/PotokThread.h:20: undefined reference to `vtable for PotokThread'

В  potok.с
   Pt=new PotokThread;

 В чем дело?



Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: Авварон от Август 07, 2009, 09:12
виртуальная функция не реализована (просто переопределения недостаточно, нужно тело). Кстати PotokThread переводится как НитьНить%)


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 07, 2009, 12:09
Ура, все заработало! Огромное спасибо за помощь.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 07, 2009, 14:02
Все заработало, но есть вопрос. Что такое emit? Что то я не найду про это ничего.
Есть только в примере Qt, а отдельно нигде нет. Просветите, пожалуйста.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: uriel от Август 07, 2009, 14:38
А вообще присоединяюсь к вопросу. :)
Всегда интересовало, на кой чёрт он нужен, если препроцессором он всё равно разворачивается в пустую строку, а код прекрасно работет и без него.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: BRE от Август 07, 2009, 14:49
А вообще присоединяюсь к вопросу. :)
Всегда интересовало, на кой чёрт он нужен, если препроцессором он всё равно разворачивается в пустую строку, а код прекрасно работет и без него.
Все уже обсуждали:
http://www.prog.org.ru/topic_8567_0.html
 ;)


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: uriel от Август 07, 2009, 16:18
Все уже обсуждали:
http://www.prog.org.ru/topic_8567_0.html
 ;)
Аха, благодарю. Видимо, тогда я эту тему так и не дочитал до конца. :)
Выходит, что из основных применений у него только одно - наглядность.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 10, 2009, 08:19
А функция сигнал реализуется самой библиотекой?! Я думал, что я сам ее должен реализовывать. Так?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: lit-uriy от Август 10, 2009, 08:26
Сигнал - чисто виртуальная функция (для програмиста), т.е. объявление без реализации. (Реализацией занимается moc - мета-объектный компилятор)


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 10, 2009, 10:14
А какое должно быть соотношение параметров сигнала и слота? Параметры должны совпадать? Или возможно несовпадение?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: uriel от Август 10, 2009, 10:58
Первые параметры сигнала должны совпадать с параметрами слота.
Например, может быть так:
Сигнал: (QString, QString) -> Слот: ()
() -> (int = 0)
(int, QString) -> (int)
А так быть не может:
()- > (int)
(QString) -> (int)
(QString, int) -> (int = 0)
P.S. Если где-то ошибся, поправьте, пожалуйста.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 11, 2009, 09:03
Есть такой код:
   Pt=new PotokThread((QObject*)this);
   QObject::connect(ui.MyRun, SIGNAL(clicked()),this, SLOT(ZapuskThread()));
Вопрос: когда поток закрыт по quit();, то Pt еще имеет смысл, или уже удаляется из памяти?

И можно ли по ходу программы создавать потоки и конекты с ними, а потом удалять конекты и потоки?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: spectre71 от Август 11, 2009, 10:41
Есть такой код:
   Pt=new PotokThread((QObject*)this);
   QObject::connect(ui.MyRun, SIGNAL(clicked()),this, SLOT(ZapuskThread()));
Вопрос: когда поток закрыт по quit();, то Pt еще имеет смысл, или уже удаляется из памяти?

И можно ли по ходу программы создавать потоки и конекты с ними, а потом удалять конекты и потоки?
1) Если сделать так
Код
C++ (Qt)
 Thread = new MyThread;
 connect(Thread , SIGNAL(finished()), Thread , SLOT(deleteLater()));
 Thread->start();
То, объект Thread удалиться сам по завершению потока.
Соответственно, после Thread->start() использовать объект Thread в главном потоке нельзя, поскольку неизвестно когда поток завершиться и объект Thread будет удален из памяти.

2)  Если сделать так
Код
C++ (Qt)
 Thread = new MyThread;
 connect(Thread , SIGNAL(finished()), MyWidget , SLOT(myThreadFinishedSlot()));
 Thread->start();
То, необходимо отследить момент завершения потока(SIGNAL(finished())) и самостоятельно удалить объект Thread.
Соответственно,  можно  использовать объект Thread в главном потоке до его самостоятельного удаления.
myThreadFinishedSlot - слот у MyWidget который необходимо определить чтобы отследить момент завершения потока.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 12, 2009, 09:43

Что то у меня работает, но не так. Есть:

Potok::Potok(QWidget *parent)
    : QWidget(parent)
{
   ui.setupUi(this);
   Pt=new PotokThread((QObject*)this);
   QObject::connect(ui.MyRun, SIGNAL(clicked()),this, SLOT(ZapuskThread()));
   connect(Pt , SIGNAL(finished()), Pt , SLOT(deleteLater()));
   QObject::connect(Pt, SIGNAL(valueChanged(int)), ui.Zapolnenie, SLOT(setValue(int)), Qt::QueuedConnection);
};

  Нажимаю на кнопку MyRun, начинается отсчет времени и отображение этого процесса на прогрессбаре ui.Zapolnenie,
по окончанию цикла, Pt не удаляется, но если я нажимаю на MyRun еще раз (после завершения цикла), то завершается вся программа без какого либо сообщения. Вопрос, почему?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: spectre71 от Август 12, 2009, 10:33

Что то у меня работает, но не так. Есть:

Potok::Potok(QWidget *parent)
    : QWidget(parent)
{
   ui.setupUi(this);
   Pt=new PotokThread((QObject*)this);
   QObject::connect(ui.MyRun, SIGNAL(clicked()),this, SLOT(ZapuskThread()));
   connect(Pt , SIGNAL(finished()), Pt , SLOT(deleteLater()));
   QObject::connect(Pt, SIGNAL(valueChanged(int)), ui.Zapolnenie, SLOT(setValue(int)), Qt::QueuedConnection);
};

  Нажимаю на кнопку MyRun, начинается отсчет времени и отображение этого процесса на прогрессбаре ui.Zapolnenie,
по окончанию цикла, Pt не удаляется, но если я нажимаю на MyRun еще раз (после завершения цикла), то завершается вся программа без какого либо сообщения. Вопрос, почему?

Pt=new PotokThread((QObject*)this); - создается  только 1 раз - в конструкторе! На deleteLater - объект Pt уничтожается. После уничтожения Pt - вызов Pt->start() приводит к ошибке!
Делать надо так:
Код
C++ (Qt)
Potok::Potok(QWidget *parent)
   : QWidget(parent)
{
ui.setupUi(this);
QObject::connect(ui.MyRun, SIGNAL(clicked()),this, SLOT(ZapuskThread()));
};
 
void Potok::ZapuskThread (void) {
Pt=new PotokThread((QObject*)this);
connect(Pt , SIGNAL(finished()), Pt , SLOT(deleteLater()));
QObject::connect(Pt, SIGNAL(valueChanged(int)), ui.Zapolnenie, SLOT(setValue(int)), Qt::QueuedConnection);
       Pt->start();
}
 


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 12, 2009, 12:28
Да, действительно в Pt дело! А почему мне не было выдано сообщение об ошибке указателя? Программа просто завершалась. Я работаю в Eclipse, может в ней дело?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 13, 2009, 08:57
Запускаю поток, идет отсчет времени и отображение процесса в прогрессбаре.
Жму крестик - завершение программы, мне выдается сообщение:
QThread: Destroyed while thread is still running
Так и должно быть? Или надо как то обрабатывать поток и завершать его?


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: pastor от Август 14, 2009, 11:45
Так и должно быть? Или надо как то обрабатывать поток и завершать его?

Такого недолжно быть. Нужно корректно завершать работу потока(ов).

Покажи код деструктора потока.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 14, 2009, 12:40
В потоке деструктор пустой, ничего не делает.


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: pastor от Август 14, 2009, 13:58
Покажи тогда метод run()


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: a_n_y_a от Август 17, 2009, 09:01
Покажи тогда метод run()

Вот:
PotokThread::~PotokThread()
{
   // TODO Auto-generated destructor stub
};

void PotokThread::run()
{
   // TODO Auto-generated destructor stub
   int i;
   for(i=100;i>=0;i--)
   {
      msleep(100);
      emit valueChanged(i);
   };
};


Название: Re: Как запустить в Qt новый процесс (или поток) в виде функции?
Отправлено: pastor от Август 17, 2009, 10:36
Попробуй например так:

Код
C++ (Qt)
class PotokThread : public QThread
{
   Q_OBJECT
....
public slots:
   void exitThread();
 
private:
   QMutex m_stopMutex;
   bool m_stopped;
};
 
 
 
PotokThread::~PotokThread()
{
exitThread();
};
 
void PotokThread::exitThread()
{
if (!isRunning())
return;
m_stopMutex.lock();
       m_stopped = true;
       m_stopMutex.unlock();
wait();
}
 
void PotokThread::run()
{
   m_stopMutex.lock();
   m_stopped = false;
   m_stopMutex.unlock();
 
  for(int i=100;i>=0 && !m_stopped;--i)
  {
     msleep(100);
     emit valueChanged(i);
  };
};