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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Усыпить главный поток, не блокируя его.  (Прочитано 6544 раз)
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;
}

}
« Последнее редактирование: Апрель 28, 2010, 18:55 от myr » Записан
sne
Гость
« Ответ #1 : Апрель 28, 2010, 16:51 »

qApp->processEvents() вставить в цикл.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #2 : Апрель 28, 2010, 16:52 »

myr, пользуйся тегом code для оформления сообщений.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
myr
Гость
« Ответ #3 : Апрель 28, 2010, 18:55 »

qApp->processEvents() вставить в цикл.
Есть уже
Записан
BRE
Гость
« Ответ #4 : Апрель 28, 2010, 19:29 »

Из главного окна запускаються 2 потока.
Первый работает с БД.
Второй ,в это время , отрисовывает progressbar на главном окне.
Для чего запускать новый поток и останавливать главный? Почему не нагрузить в это время его?
Запусти один поток для работы с БД, а в главном потоке показывай progress.

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

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Апрель 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
« Последнее редактирование: Апрель 28, 2010, 19:39 от Igors » Записан
myr
Гость
« Ответ #6 : Апрель 29, 2010, 08:24 »

Спасибо. Уберу второй поток. Это я перемудрила.

Записан
myr
Гость
« Ответ #7 : Апрель 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();

}
Записан
BRE
Гость
« Ответ #8 : Апрель 29, 2010, 10:32 »

И все таки. Пока работает главный поток, второй блокируеться. Как Усыпить главную нитку, чтобы выполнилась вторая.
Не может он блокироваться, если ты сама его не заблокируешь.

Какой версией Qt ты пользуешься?
 
Записан
myr
Гость
« Ответ #9 : Апрель 29, 2010, 10:47 »

QT 3.3
Нужно запустить нитку, которая работает с БД .
И пока идет обработка выводить прогресс бар.
Записан
BRE
Гость
« Ответ #10 : Апрель 29, 2010, 11:02 »

Не нужно здесь processEvents вызывать.
Код:
void TThreadBD::run()
{
int i=0;
//readFromBd();
for(i =0 ;i< 10;i++)
{
     usleep(100);
//             qApp->processEvents(); // <<<<<<<<<<<

}

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

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Апрель 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);
}
 
Записан
myr
Гость
« Ответ #12 : Апрель 29, 2010, 13:29 »

Ура. Все заработало.
Спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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