crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> проблема с потоками Thread в Qt
Гость_Сергей_*
сообщение 24.11.2010, 10:50
Сообщение #1





Гости








    


задача такая, нужно создать несколько потоков, в частности 3, причем чтобы из первого потока запускался второй, из второго третий, а в третьем производились вычисления.
информацию о состоянии вычислений третьего потока нужно вывести на progressBar формы.
я использую сигнально слотовые соединения т.е
запускаю первый поток:

void MainWindow::on_pushButton_clicked()
{
    ThMain_1 *MAIN_1 = new ThMain_1;
    MAIN_1->start();
    connect(MAIN_1,SIGNAL(progress_th_2(int)),this,SLOT(on_progressBar_2_valueChanged(int)));

}

void MainWindow::on_progressBar_2_valueChanged(int value)
{
    ui->progressBar_2->setValue(value);
}

запускаю второй поток:
void ThMain_1::run()
{
    ThSub_1 *THSUB_1 = new ThSub_1;
    THSUB_1->start();
    connect(THSUB_1,SIGNAL(progress_th_2(int)),this,SLOT(SetProgress_th_2(int)));
}

void ThMain_1::SetProgress_th_2(int progress)
{
   emit progress_th_2(progress);
  }

запускаю третий поток
void ThSub_1::run()
{
th_2 *TH_2 = new th_2;
TH_2->start();
connect(TH_2,SIGNAL(progress_2(int)),this,SLOT(SetProgress_th_2(int)))
}

void ThSub_1::SetProgress_th_2(int progress)
{
  emit progress_th_2(progress);
}

произвожу в третьем потоке вычисления
void th_2::run()
{
    int __progress=0;
    double _result=0;
     for (int i=0; i<=199800; i++)
        {
          _result+=cos(atan(i));
          if (i%1998==0)
          {
              emit progress_2(++__progress);
          }
        }
}

и посылаю состояние вычислений через все потоки в форму.
но почему то не работает. Подскажите, в чем может быть поблема-ошибка.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.11.2010, 11:05
Сообщение #2


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(Гость_Сергей_* @ 24.11.2010, 10:50) *
 connect(THSUB_1,SIGNAL(progress_th_2(int)),this,SLOT(SetProgress_th_2(int)));  
...
void ThMain_1::SetProgress_th_2(int progress)
{    
emit progress_th_2(progress);  
}

сигналы можно напрямую друг с другом соединять.

Цитата(Гость_Сергей_* @ 24.11.2010, 10:50) *
TH_2->start(); 
connect(TH_2,SIGNAL(progress_2(int)),this,SLOT(SetProgress_th_2(int)))

может поток уже все "отработал"(уже вызвал сигнал, который остался без обработчика) и только потом произошло соединение.
попробуй эти строки местами поменять
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Сергей_*
сообщение 24.11.2010, 14:27
Сообщение #3





Гости








    


Спасибо за совет, я переделал немного код, в результате получилось
void MainWindow::on_pushButton_clicked()
{
    ThMain_1 *MAIN_1 = new ThMain_1;
    connect(MAIN_1,SIGNAL(progress(int)),this,SLOT(on_progressBar_valueChanged(int)));
    MAIN_1->start();
}

void MainWindow::on_progressBar_valueChanged(int value)
{
    ui->progressBar->setValue(value);
}


//2

void ThMain_1::run()
{
  ThSub_1 *THSUB_1 = new ThSub_1;
  connect(THSUB_1,SIGNAL(progress(int)),this,SIGNAL(progress(int)));
  THSUB_1->start();
}


//3
void ThSub_1::run()
{

    Th_1 *TH_1 = new Th_1;
    connect(TH_1,SIGNAL(progress(int)),this,SIGNAL(progress(int)));
    TH_1->start();
}

//вычисления (для теста полставил вместо вычислений)

void Th_1::run()
{

    for (int i=1; i<=100; i++)
    {
     sleep(1);
     emit progress(i);
     }

}


но не помогло, всё равно сигнал не доходит, Но если вычесления делать не в Th_1 а в предыдущем потоке то сигнал доходит.... вот как бы и продлема
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 24.11.2010, 17:34
Сообщение #4


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


можно проверить что возвращает connect во всех случаях соединения.
в консоль предупреждения не сыпятся во время выполнения программы?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 24.11.2010, 18:06
Сообщение #5


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


я не спец в QT, но есть предположение, что внутри обработки сигнала повторный вызов этого же сигнала просто "гасится". то есть, функция
void ThMain_1::SetProgress_th_2(int progress) 
{    
emit progress_th_2(progress);  
}

просто ничего не выполняет, ибо всё это происходит внутри обработчика сигнала и сигнал после выхода тупо сбрасывается. попробуй использовать два сигнала - может, сработает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Сергей_*
сообщение 25.11.2010, 0:04
Сообщение #6





Гости








    


Нет, в консоли отладки никаких сообщний нет, но вот что я приметил: выставив точки останова при отладке, получается так, что сигнал из
void Th_1::run()
{

    for (int i=1; i<=100; i++)
    {
     sleep(1);
      emit progress(100);
     }

}


не попадает в
 
void ThSub_1::SetProgress_th_2(int progress)
{
  emit progress_th_2(progress);
}


либо наоборот последний не принимает сигнал. Как считаете, может ли это зависеть от конкретно операционной системы(сижу под Fedora 14).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 25.11.2010, 0:35
Сообщение #7


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


читай про реализацию QT сигналов в многопоточных приложениях и проверяй области видимости. может, у тебя process банально разрушается до того момента, как его успеют вызвать, или ещё где-то какие-нибудь локальные переменные задействованы.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xls
  опции профиля:
сообщение 26.11.2010, 9:51
Сообщение #8


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 6.9.2010
Пользователь №: 2013

Спасибо сказали: 7 раз(а)




Репутация:   2  


Привет.
Ваша проблема в том, что все вызовы connect связывают сигналы и слоты объектов, находящихся в одном потоке ( да, сам объект потока находится в том потоке, в котором он был создан ) и это вызывает соединение типа Qt::DirectConnection, а не желаемое Вам Qt::QueuedConnection.
Для того, чтобы реализовать желаемое поведение можно поступить следующим образом ( рассмотрим простейший случай - два потока ).
1. Создать дочерний поток (ДП).
2. Создать в дочернем потоке объект с сигналом "прогресс".
3. Связать сигнал дочернего потока "прогресс" с сигналом созданного объекта "прогресс".
4. Связать сигнал объекта со слотом главного потока.
5. Вызывать сигнал ДП.
Для дважды дочерний потока ( ДДП ) аналогично создается объект, он связывается с сигналом ДДП, а затем с сигналом ДП, он вызовет свой объект, который свяжется с главным потоком асинхронно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Сергей_*
сообщение 30.11.2010, 13:53
Сообщение #9





Гости








    


Цитата(xls @ 26.11.2010, 9:51) *
Привет.
Ваша проблема в том, что все вызовы connect связывают сигналы и слоты объектов, находящихся в одном потоке ( да, сам объект потока находится в том потоке, в котором он был создан ) и это вызывает соединение типа Qt::DirectConnection, а не желаемое Вам Qt::QueuedConnection.
Для того, чтобы реализовать желаемое поведение можно поступить следующим образом ( рассмотрим простейший случай - два потока ).
1. Создать дочерний поток (ДП).
2. Создать в дочернем потоке объект с сигналом "прогресс".
3. Связать сигнал дочернего потока "прогресс" с сигналом созданного объекта "прогресс".
4. Связать сигнал объекта со слотом главного потока.
5. Вызывать сигнал ДП.
Для дважды дочерний потока ( ДДП ) аналогично создается объект, он связывается с сигналом ДДП, а затем с сигналом ДП, он вызовет свой объект, который свяжется с главным потоком асинхронно.


Я наверное чего то не понял, но помоему в коде я так и делаю
Раскрывающийся текст
void MainWindow::on_pushButton_clicked()
{
    ThMain_1 *MAIN_1 = new ThMain_1;
    connect(MAIN_1,SIGNAL(progress(int)),this,SLOT(on_progressBar_valueChanged(int)));
    MAIN_1->start();
}

void MainWindow::on_progressBar_valueChanged(int value)
{
    ui->progressBar->setValue(value);
}


//2

void ThMain_1::run()
{
  ThSub_1 *THSUB_1 = new ThSub_1;
  connect(THSUB_1,SIGNAL(progress(int)),this,SIGNAL(progress(int)));
  THSUB_1->start();
}


//3
void ThSub_1::run()
{

    Th_1 *TH_1 = new Th_1;
    connect(TH_1,SIGNAL(progress(int)),this,SIGNAL(progress(int)));
    TH_1->start();
}

//вычисления (для теста полставил вместо вычислений)

void Th_1::run()
{

    for (int i=1; i<=100; i++)
    {
     sleep(1);
     emit progress(i);
     }

}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.1.2025, 9:35