Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: define от Июль 11, 2011, 16:42



Название: проблема с многопочностью
Отправлено: define от Июль 11, 2011, 16:42
Здравствуйте, пытаюсь разобраться с многопоточностью в Qt.
a.h
Код:
#include<b.h>

class a : public QWidget
{
    Q_OBJECT

public:
    a(QWidget *parent = 0);
private:
    void show(int pos);
   };
a.cpp
Код:
#include "a.h"
void a::show(int pos)
{
    th j;
    j.run(pos);
}
th.h
Код:
#include <QThread>
#include<a.h>

class th : public QThread
{
    Q_OBJECT
public:
    explicit th(QObject *parent = 0);
    void run(int h);

};
th.cpp
Код:
#include "th.h"

th::th(QObject *parent) :
    QThread(parent)
{
}
void th::run(int h)
{
 ...
}

так вот, почему поток в th идет не асинхронно?


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 11, 2011, 17:00
Потому что:
1) надо перегружать виртуальную функцию run() без всяких параметров
2) запускаться надо при помощи start(), а не run.


Название: Re: проблема с многопочностью
Отправлено: define от Июль 11, 2011, 17:07
Потому что:
1) надо перегружать виртуальную функцию run() без всяких параметров
2) запускаться надо при помощи start(), а не run.
ок, а как тогда передать в поток какой-либо параметр?


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 11, 2011, 19:44
ок, а как тогда передать в поток какой-либо параметр?
Завести член класса соответствующего типа и записать в него нужные данные. Так же можно возвращать результат, если нужно.


Название: Re: проблема с многопочностью
Отправлено: define от Июль 11, 2011, 21:41
Завести член класса соответствующего типа и записать в него нужные данные. Так же можно возвращать результат, если нужно.
можно какой-нибудь конкретный пример? Спасибо.


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 11, 2011, 22:14
a.h
Цитировать
#include<b.h>

class a : public QWidget
{
    Q_OBJECT

public:
    a(QWidget *parent = 0);
private:
    void show(int pos);
   };
a.cpp
Цитировать
#include "a.h"
void a::show(int pos)
{
    th j;
   j.pos = pos;
    j.start();

}
th.h
Цитировать
#include <QThread>
#include<a.h>

class th : public QThread
{
    Q_OBJECT
public:
    explicit th(QObject *parent = 0);
   void run();
    int j;

};
th.cpp
Цитировать
#include "th.h"

th::th(QObject *parent) :
    QThread(parent)
{
}
void th::run()
{
 ...
}
Ну и наивно надеюсь, что вы просто для примера сократили, а в настоящем коде у вас классы не называются по 1-2 буквы.


Название: Re: проблема с многопочностью
Отправлено: define от Июль 12, 2011, 10:42
Разумеется сократил)
Спасибо большое, вроде бы более менее с механизмом разобрался.


Название: Re: проблема с многопочностью
Отправлено: define от Июль 12, 2011, 14:02
Цитировать
#include "a.h"
void a::show(int pos)
{
    th j;
   j.pos = pos;
    j.start();

}
вроде бы сделал, но пишет
"QThread: Destroyed while thread is still running"
в чем проблема может быть?


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 12, 2011, 14:45
Логично, как только выходите из функции поток разрушается.
Надо либо th создавать динамически, либо выходить из функции только после завершения потока.


Название: Re: проблема с многопочностью
Отправлено: danquimby от Июль 22, 2011, 16:56
Цитировать
#include "a.h"
void a::show(int pos)
{
    th j;
   j.pos = pos;
    j.start();

}
вроде бы сделал, но пишет
"QThread: Destroyed while thread is still running"
в чем проблема может быть?

Код:
#include "a.h"
th *j;
void a::show(int pos)
{
    j = new th();
    j->pos = pos;
    j->start();
}
delete тока не забудь сделать где нить ) да и вообще странный подход )))


Название: Re: проблема с многопочностью
Отправлено: Странник от Июль 22, 2011, 22:20
где-то мне попадалось замечание, что наследование QThread больше не является рекомендуемым методом работы с потоками. я использую следующий вариант и его вариации:
Код:
QThread thread;

Worker worker;
connect(obj, SIGNAL(workReady()), &worker, SLOT(doWork()));
worker.moveToThread(&thread);

thread.start();
вызов thread.start() инициирует запуск цикла обработки событий внутри созданного потока, соответственно слоты объекта worker выполняются в этом потоке при вызове через очередь. все объекты, живущие внутри потока, необходимо удалить до его завершения.


Название: Re: проблема с многопочностью
Отправлено: ilyagoo от Июль 23, 2011, 18:37
где-то мне попадалось замечание, что наследование QThread больше не является рекомендуемым методом работы с потоками.

не вспомнишь где? интересно почитать.


Название: Re: проблема с многопочностью
Отправлено: ufna от Июль 24, 2011, 19:06

не вспомнишь где? интересно почитать.

попадалось на лабах троллей по-моему, но имхо это хрень полная


Название: Re: проблема с многопочностью
Отправлено: Пантер от Июль 25, 2011, 09:09
где-то мне попадалось замечание, что наследование QThread больше не является рекомендуемым методом работы с потоками.
не вспомнишь где? интересно почитать.
Было на данном форуме - поищи.


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 25, 2011, 10:09
Тем не менее в справке приводится пример именно с переопределением run().


Название: Re: проблема с многопочностью
Отправлено: Странник от Июль 25, 2011, 14:34
да, на лабах попадалось, но что-то не найду. что касается документации по qthread, сообщество просит дополнения: http://developer.qt.nokia.com/doc/qt-4.7/qthread.html


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 25, 2011, 14:45
Кстати в этом новом примере совершенно не очевидно где безопасно уничтожить worker и как об этом не забыть.


Название: Re: проблема с многопочностью
Отправлено: Странник от Июль 25, 2011, 15:01
Кстати в этом новом примере совершенно не очевидно где безопасно уничтожить worker и как об этом не забыть.

это всего лишь предложение дополнить документацию, могут и сами исчерпывающий пример на эту тему написать = ) а для любопытствующих в конце заметки приведена ссылка:
Цитата: Andre
Many more hints and details, including the pitfalls of using QThread in combination with signals and slots, can be found this must read wiki article (http://developer.qt.nokia.com/wiki/Threads_Events_QObjects) [developer.qt.nokia.com].


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Июль 25, 2011, 15:11
а для любопытствующих в конце заметки приведена ссылка
Там нет ответа на мой вопрос.


Название: Re: проблема с многопочностью
Отправлено: Странник от Август 04, 2011, 14:56
Там нет ответа на мой вопрос.
там есть все, что нужно знать, чтобы сделать это верно. а однозначного ответа по-моему не существует, все зависит от архитектуры приложения. worker должен быть уничтожен до завершения event loop потока. грубо говоря:
Код:
QThread *thread = new QThread;

Worker *worker = new Worker;
worker->moveToThread(thread);

thread->start();

connect(this, SIGNAL(workReady()), worker, SLOT(doWork()));
connect(worker, SIGNAL(workDone()), this, SLOT(processResult()));
connect(worker, SIGNAL(destroyed()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
остается не забыть удалить объект worker, когда он больше не нужен. например, в processResult() вызовом Worker::deleteLater() через очередь.


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Август 04, 2011, 15:39
В общих чертах понятно, хотя если приложение закрывают, то в главном потоке мы вываливаемся из QCoreApplication::exec() и дальше завершения потоков мы не дождёмся никогда - последние 2 коннекта не сработают так как обработчика событий в главном потоке уже нету (для тех QThread что были порождены в главном потоке).
Ну а не дожидаться окончания работы воркером может быть чревато битыми файлами и прочими пузиблинчиками ( в зависимости от того, что делают данные воркеры ).


Название: Re: проблема с многопочностью
Отправлено: Paul от Август 17, 2011, 15:18
Добрый день, коллеги. Есть вопрос по потокам: для работы клиента создал объект, к-ый использует 3 дочерних потока (приёмник, обработчик и передатчик), которые создаются и стартуют в конструкторе объекта. Чтобы рабочие данные принадлежали самим потокам, их создание и cоnnect-ы определены в run(). Если в главной прог-е создание и выполнение
1-ой операции выполнить без задержки, то "дочки-поточки" не успевают "разогнаться" полностью, т.к. start() только запускает run() и не ждёт его выполнения, что понятно (если exec(), то не дождёшься).
НУЖНА ПАУЗА !!!

Я по своей малости знания QT решил задачку так: разделил создание и выполнение 1-ой операции на две функции, в конце 1-ой (после создания объекта в окне) выполнил
QTimer::singleShot(500, this, SLOT(executOper()));
где, как легко догадаться executOper() - выполнение операции.

С моей колокольни - как-то коряво. Так и хочется после start() написать wait(), но для какого потока ??? У меня не получилось. Поделитесь пожалуйста знаниями.
   С уважением, Paul


Название: Re: проблема с многопочностью
Отправлено: LisandreL от Август 17, 2011, 15:30
1-ой операции выполнить без задержки, то "дочки-поточки" не успевают "разогнаться" полностью, т.к. start() только запускает run()
И? Покажите что вы пытаетесь сделать с потоками.
Чего вы дождаться хотите? exec()? Входа в run()? Выхода из run()?