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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Создание второго потока под вычисления.  (Прочитано 12507 раз)
Crazy Sage
Гость
« : Март 19, 2009, 09:43 »

Задача сделать программу в два потока, во втором - очередь вычислительных задач.
Вопрос первый: надо ли создавать отдельно поток под основную программу или если я из нее создам отдельно поток под вычисления все будет нормально?
Вопрос второй: начал писать своего наследника QThread
Код:
class MThread : public QThread
{
  Q_OBJECT
public:
MThread(double x, unsigned int stackSize = 0);
virtual ~MThread();
double getX();
void setX (double x);
protected:
void run();
private:
double x;

};

при наличии макроса Q_OBJECT выдает
moc_mthread.cpp:54: error: 'staticMetaObject' is not a member of 'QThread'
moc_mthread.cpp:72: error: 'qt_cast' is not a member of 'QThread'
moc_mthread.cpp:77: error: 'qt_invoke' is not a member of 'QThread'
moc_mthread.cpp:82: error: 'qt_emit' is not a member of 'QThread'
moc_mthread.cpp:88: error: 'qt_property' is not a member of 'QThread'

если его закомменить

mthread.cpp:5: undefined reference to `vtable for MThread'
mthread.cpp:5: undefined reference to `vtable for MThread'

в чем ошибка?

текст cpp файла:
Код:
MThread::MThread ( double x, unsigned int stackSize) :QThread( stackSize)
{
this->x=x;
                this->run();
}

void MThread::setX ( double x )
{
this->x=x;
}

double MThread::getX()
{
return this->x;
}

void MThread::run()
{
long i;
int j=0;
int progress;
for ( i=0;i<1000000;i++ )
{
setX ( sin ( this->getX() ) );
j+=1;
if ( j==10000 )
{
progress=dlgMain->taskProgress->progress();
dlgMain->taskProgress->setProgress ( progress+1 );
j=0;
}
}
QString ds = QString( "'E' format, precision 3, gives %1" )
                    .arg( x, 0, 'E', 3 );
dlgMain->logAdd(ds);
}
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Март 19, 2009, 09:54 »

при наличии макроса Q_OBJECT выдает

Пересобери проект: qmake && make

И сразу вопросы по потоку...

1)
Код
C++ (Qt)
MThread::MThread ( double x, unsigned int stackSize) :QThread( stackSize)
{
this->x=x;
               this->run();
}

Это запуск потока на выполнение? Если да, то неверно. Для запуска потока нужно вызывать start

2) dlgMain - это что? Какой-то диалог с прогрессбаром? Снова неверно, во вспомогательном потоке нельзя работать с GUI.

3) Член "x" класса MThread незащищен объектом синхронизации

Вывод: вспомогательный поток в текущем виде не работоспособен.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
igor_bogomolov
Гость
« Ответ #2 : Март 19, 2009, 10:08 »

А что такое stackSize? И почему он в QThread передается?
Разве не обязан конструктор MThread приничать указатель на QObject, и передовать его дальше в QThread?
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Март 19, 2009, 10:10 »

А что такое stackSize? И почему он в QThread передается?
Разве не обязан конструктор MThread приничать указатель на QObject, и передовать его дальше в QThread?

Очевидно Crazy Sage использует Qt3
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Crazy Sage
Гость
« Ответ #4 : Март 19, 2009, 10:21 »

И сразу вопросы по потоку...
3) Член "x" класса MThread незащищен объектом синхронизации

Вывод: вспомогательный поток в текущем виде не работоспособен.

проблемы с синхронизацией я буду решать уже потом, пока я просто пытаюсь сделать программу, в которой можно запустить второй поток, который будет считать что-то, перерисовывая прогресс бар не блокируя при этом работу основной программы

Очевидно Crazy Sage использует Qt3

да и возможности перейти на qt4 у меня нет
« Последнее редактирование: Март 19, 2009, 10:43 от Crazy Sage » Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #5 : Март 19, 2009, 10:42 »

это главное окно, в котором среди прочего есть прогрессбар.
как тогда из вспомогательного потока по ходу выполнения менять значение прогрессбара?

Передавать это значение в главный поток (GUI thread) при помоши custom event + QApplication::postEvent главному окну. Там (в главном потоке) его обрабатывать и устанавливать значение прогрессбару
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Crazy Sage
Гость
« Ответ #6 : Март 19, 2009, 12:06 »

Насколько корректен такой вариант (если не считать абсолютно наплевательского отношения к целостности данных)
Код:
ProgressEvent::ProgressEvent():QCustomEvent(progressChange) //в .h файле есть перечисление, в котором указан номер progressChange'а
{
}

int ProgressEvent::getProgress()
{
return this->progress;
}

void ProgressEvent::setProgress(int p)
{
this->progress=p;
}

MThread::MThread ( double x, unsigned int stackSize) :QThread( stackSize)
{
this->x=x;
this->start();
}

void MThread::setX ( double x )
{
this->x=x;
}

double MThread::getX()
{
return this->x;
}

void MThread::run()
{
long i;
QString s;
int progress=0;

qDebug("start computing");
for ( i=0;i<100;i++ )
{
qDebug("Another step");
this->x=sin(this->x);
progress+=1;
ProgressEvent *e = new ProgressEvent;
e->setProgress(progress);
QApplication::postEvent(dlgMain,e);
qDebug("Send event");
this->sleep(1);
qDebug("Sleep over");
}
progress+=1;
ProgressEvent *e = new ProgressEvent;
e->setProgress(progress);
QApplication::postEvent(dlgMain,e);

QString ds = QString( "'E' format, precision 3, gives %1" )
                    .arg( x, 0, 'E', 3 );
dlgMain->logAdd(ds);
this->exit();
}

P.S. и еще, посоветуйте, как сделать паузу\возобновление потока посреди выполнения?
и можно ли его остановить во время run если просто выполнить ему thread->terminate()
« Последнее редактирование: Март 19, 2009, 12:08 от Crazy Sage » Записан
BRE
Гость
« Ответ #7 : Март 19, 2009, 12:21 »

P.S. и еще, посоветуйте, как сделать паузу\возобновление потока посреди выполнения?
Не совсем понятно, приостановить выполнение во время расчета или между расчетами?

и можно ли его остановить во время run если просто выполнить ему thread->terminate()
А зачем убивать, если можно сделать флажок, который поток будет проверять в на каждой итерации и если надо выходить из цикла - завершая поток.
Записан
Crazy Sage
Гость
« Ответ #8 : Март 19, 2009, 12:31 »

Не совсем понятно, приостановить выполнение во время расчета или между расчетами?

во время
Записан
BRE
Гость
« Ответ #9 : Март 19, 2009, 12:35 »

во время

Поменяй, чуть чуть цикл:
Код
C++ (Qt)
while( m_running )
{
   if( m_pause )
        continue;
 
    Считаем следующую итерацию
    Отправляем сообщение на обновление прогрессбара.
 
    Если все посчитали, выходим из цикла (по break или m_running = false)
}
 
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #10 : Март 19, 2009, 13:00 »

и можно ли его остановить во время run если просто выполнить ему thread->terminate()

можно, но terminate использовать не желательно. Используй пару exit и wait
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #11 : Март 19, 2009, 13:03 »

Конструкция вида:


Код
C++ (Qt)
while( m_running )
{
   if( m_pause )
        continue;
   ....
}
 

будет грузить проц. ТОгда уж так:

Код
C++ (Qt)
while( m_running )
{
   if( m_pause ) {
        msleep(50);
        continue;
   }
   ....
}
 
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
BRE
Гость
« Ответ #12 : Март 19, 2009, 13:21 »

Код
C++ (Qt)
while( m_running )
{
   if( m_pause ) {
        msleep(50);
        continue;
   }
   ....
}
 
pastor, ну это же был псевдокод, последние три строки в моем примере, некоторые компиляторы не пропустили бы.  Подмигивающий

Для этого случая, я бы наверное мьютекс задействовал.
« Последнее редактирование: Март 19, 2009, 13:23 от BRE » Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #13 : Март 19, 2009, 13:40 »

pastor, ну это же был псевдокод, последние три строки в моем примере, некоторые компиляторы не пропустили бы.  Подмигивающий

Для этого случая, я бы наверное мьютекс задействовал.

Тогда сорри Подмигивающий

А идея с мютексом весьма неплохая Улыбающийся
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
yesrus
Гость
« Ответ #14 : Март 19, 2009, 17:53 »

Посмотрите эту тему http://www.prog.org.ru/topic_8844_0.html - много вопросов прояснится(в частности лучше поток делать с эвент лупом(а не с бесконечным циклом) и передавать даннные на обработку с помощью сигналов...)
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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