Russian Qt Forum

Qt => Общие вопросы => Тема начата: myr от Апрель 28, 2010, 16:11



Название: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 28, 2010, 16:11
Здраствуйте, помогите, пож-та.
Есть приложение.
Из главного окна запускаються 2 потока.
Первый работает с БД.
Второй ,в это время , отрисовывает progressbar на главном окне.
Во время выполнения цикла никакие события не приходят. Почему?
Спасибо
Что можно использовать вместо sleep()?.

Код:
bool read{ // вызываеться из главного потока
  TThreadBD *threadBD = new TThreadBD(obj,qry,str);
  threadBD->start();
  TThreadProgress * threadProgress = new TThreadProgress(qApp->mainWidget());
  threadProgress->start();
  
  int i =0 ;
  //QWaitCondition waitCondition;

  while((threadBD->finished () == false)&& (i < 1000000)){
     //  waitCondition.wait(10);
  qApp->processEvents();
     i++;
  }

 if(threadBD->finished () == false)
  threadBD->terminate () ;
 threadProgress->terminate();
  return
}

Код:
void frmMain::customEvent( QCustomEvent *pe )
{
    if((int)pe->type() == TEventProgress::TypeEvent){
           int t = ((TEventProgress*)(pe))->value()     ;
  progressbar->setProgress(t);
 }
    else
     QWidget::customEvent(pe);
 
}
Код:
class TThreadProgress:public QThread{
private:
QObject * m_pobjReceiver;
volatile bool stoped;
public:
  TThreadProgress(QObject * pobjReceiver);
   virtual void run();
   void stop();

};

class TEventProgress: public QEvent  {
private:
int m_nValue;
public:
enum {TypeEvent = User+1};  
           TEventProgress():QEvent((Type)TypeEvent){}
void setValue(int n);
int value() const;
};


void TThreadProgress::run()
{
int i=0;
while((stoped == false) && (i < 10000)){
        usleep(10);
            TEventProgress * pe = new TEventProgress();
     pe->setValue(i);
 QApplication::postEvent(qApp->mainWidget(),pe);
   qApp->processEvents();
 i++;
}
        stoped =true;
}
void TThreadProgress::stop()
{
   stoped = true;
}



void TEventProgress::setValue(int n)
{
m_nValue =n ;
}

int TEventProgress::value() const
{
return m_nValue;
}

}


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: sne от Апрель 28, 2010, 16:51
qApp->processEvents() вставить в цикл.


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: Пантер от Апрель 28, 2010, 16:52
myr, пользуйся тегом code для оформления сообщений.


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 28, 2010, 18:55
qApp->processEvents() вставить в цикл.
Есть уже


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: BRE от Апрель 28, 2010, 19:29
Из главного окна запускаються 2 потока.
Первый работает с БД.
Второй ,в это время , отрисовывает progressbar на главном окне.
Для чего запускать новый поток и останавливать главный? Почему не нагрузить в это время его?
Запусти один поток для работы с БД, а в главном потоке показывай progress.



Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: Igors от Апрель 28, 2010, 19:36
Сюжет: не надо никого усыплять, просто запускаете нитку и она читает БД. Она же обновляет индикатор (можно через тот же postEvent), совершенно незачем делать еще 1 нитку для индикатора. Примерно так (псевдокод)
Код
C++ (Qt)
void frMain::StartRead( void )
{
 threadBD = new TThreadBD(obj,qry,str);
 connect(threadBD, SIGNAL(finished()), this, SLOT(EndRead()));
 progressbar->setValue(0);
 progressbar->show();
 threadBD->start();
}
 
void frMain::EndRead( void )
{
 delete threadBD;
 threadBD = 0;
 progressbar->hide();
}
 
Еще лучше сделать progressbar членом TThreadBD и создавать/удалять его в конструкторе/деструкторе TThreadBD


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 29, 2010, 08:24
Спасибо. Уберу второй поток. Это я перемудрила.



Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 29, 2010, 10:27
И все таки. Пока работает главный поток, второй блокируеться. Как Усыпить главную нитку, чтобы выполнилась вторая.
Из второй нити обновлять прогресс - не подходит.

Код:
bool frmMain::readFromBD( QSqlQuery qry, QString str )


   TThreadBD *pthreadBD = new TThreadBD(this,qry,str);
   
   pthreadBD->start();
   int i =0 ;
   progressbar->setTotalSteps (10000);
   //QWaitCondition waitCondition;
   while( pthreadBD->finished () == false) {
            progressbar->setProgress(i);
// waitCondition.wait(100);
i++;
qApp->processEvents();
   
   }

Код:
void TThreadBD::run()
{
int i=0;
//readFromBd();
for(i =0 ;i< 10;i++)
{
     usleep(100);
             qApp->processEvents();

}


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: BRE от Апрель 29, 2010, 10:32
И все таки. Пока работает главный поток, второй блокируеться. Как Усыпить главную нитку, чтобы выполнилась вторая.
Не может он блокироваться, если ты сама его не заблокируешь.

Какой версией Qt ты пользуешься?
 


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 29, 2010, 10:47
QT 3.3
Нужно запустить нитку, которая работает с БД .
И пока идет обработка выводить прогресс бар.


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: BRE от Апрель 29, 2010, 11:02
Не нужно здесь processEvents вызывать.
Код:
void TThreadBD::run()
{
int i=0;
//readFromBd();
for(i =0 ;i< 10;i++)
{
     usleep(100);
//             qApp->processEvents(); // <<<<<<<<<<<

}

Тестовый поток отработает очень быстро, результат ты скорее всего не увидишь.
Увеличь задержку:
sleep( 1 );


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: Igors от Апрель 29, 2010, 12:17
Из второй нити обновлять прогресс - не подходит.
Подходит если делать через сигнал (а можно и через postEvent)
Код
C++ (Qt)
void TThreadBD::run()
{
//readFromBd();
for(int i =0 ; i < 1000; i++)
{
    usleep(1000);
          emit progressUpdate(i);
}
}
 
void frmMain::progressUpdate( int value )
{
   progressbar->setProgress(value);
}
 


Название: Re: Усыпить главный поток, не блокируя его.
Отправлено: myr от Апрель 29, 2010, 13:29
Ура. Все заработало.
Спасибо.