crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> Многопоточность в Qt, Проблемы с QThread
silart
  опции профиля:
сообщение 4.6.2008, 8:06
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 15
Регистрация: 31.3.2008
Пользователь №: 138

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




Репутация:   0  


Добрый день! Подскажите пожалуйста, кто работал с QThread, каким образом сделать так, чтобы сигналы объекта обрабатывались пользовательским потоком, а не потоком графического интерфейса. Вот у Шлее есть 2 примера:

Первый:
#include <QtGui>

// ======================================================================
class MyThread : public QThread {
Q_OBJECT
private:
    int m_nValue;

public:
    MyThread() : m_nValue(10)
    {
    }

    void run()
    {
        QTimer timer;
        connect(&timer, SIGNAL(timeout()), SLOT(slotNextValue()));
        timer.start(1000);

        exec();
    }

signals:
    void finished    (   );
    void currentValue(int);

public slots:
    void slotNextValue()
    {
        emit currentValue(--m_nValue);

        if (!m_nValue) {
            emit finished();
        }
        
    }
};

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QLCDNumber   lcd;
    MyThread     thread;

    QObject::connect(&thread, SIGNAL(currentValue(int)),
                     &lcd,    SLOT(display(int))
                    );
    QObject::connect(&thread, SIGNAL(finished()),
                     &app,    SLOT(quit())
                    );

    lcd.setSegmentStyle(QLCDNumber::Filled);
    lcd.display(10);
    lcd.resize(220, 90);
    lcd.show();
    thread.start();

    return app.exec();
}

#include "main.moc"


Второй:

#include <QtGui>

// ======================================================================
class MyThread : public QThread {
Q_OBJECT
private:
    int m_nValue;

public:
    MyThread() : m_nValue(10)
    {
    }

    void run()
    {
        exec();
    }

signals:
    void finished    (   );
    void currentValue(int);

public slots:
    void slotNextValue()
    {
        emit currentValue(--m_nValue);

        if (!m_nValue) {
            emit finished();
        }
        
    }
};

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QLCDNumber   lcd;
    MyThread     thread;

    QObject::connect(&thread, SIGNAL(currentValue(int)),
                     &lcd,    SLOT(display(int))
                    );
    QObject::connect(&thread, SIGNAL(finished()),
                     &app,    SLOT(quit())
                    );

    QTimer timer;
    QObject::connect(&timer, SIGNAL(timeout()), &thread, SLOT(slotNextValue()));
//    timer.moveToThread(&thread);
    timer.start(1000);

    lcd.setSegmentStyle(QLCDNumber::Filled);
    lcd.display(10);
    lcd.resize(220, 90);
    lcd.show();
    thread.start();

    return app.exec();
}

#include "main.moc"


Как сделать так, чтобы слот slotNextValue() обрабатывался потоком MyThread? В примерах этот слот обрабатывается главным потоком.
Есть еще функция moveToThread(), но с ней ничего вообще не получается, в слот не попадает ни один поток...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.6.2008, 8:23
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3290
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

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




Репутация:   40  


Есть замечательное правило, слот выполняется в том потоке, в котором был создан его объект.
Другими словами тебе нужно, чтобы объект слота slotNextValue создавался в потоке MyThread.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.6.2008, 9:18
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


тут почитай: Связь сигналов и слотов между потоками
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
sploid
  опции профиля:
сообщение 4.6.2008, 14:21
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 51
Регистрация: 26.2.2008
Из: Москва
Пользователь №: 106

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




Репутация:   1  


если я правильно понял вопрос, то должно быть так ( не тестил ):
// свой объект, слоты которого обрабатываются в рабочем потоке
class MyObject : public QObject
{
    Q_OBJECT
public:
    MyObject( ) : m_nValue(10){ };
signals:
    // сигнал о изменении значения.
    void currentValue(int);
    void wantQuit( );
public slots:
    void slotNextValue()
    {
        emit currentValue(--m_nValue);
        if (!m_nValue) {
           emit wantQuit( );
        }
        
    }
private:
    int m_nValue;
};

// ======================================================================
class MyThread : public QThread {
Q_OBJECT

public:
    MyThread()
    {
    }

    void run()
    {
        MyObject myObj( this );
        connect( &myObj, SIGNAL( currentValue( int ) ), SIGNAL( currentValue( int ) ) );
        connect( &myObj, SIGNAL( wantQuit( ) ), SLOT( quit( ) ) );
        QTimer timer;
        connect(&timer, SIGNAL(timeout()), &myObj, SLOT(slotNextValue()));
        timer.start(1000);

        exec();
    }
signals:
    void currentValue(int);
};

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    QLCDNumber   lcd;
    MyThread     thread;

    QObject::connect(&thread, SIGNAL(currentValue(int)),
                     &lcd,    SLOT(display(int))
                    );
    QObject::connect(&thread, SIGNAL(finished()),
                     &app,    SLOT(quit())
                    );

    lcd.setSegmentStyle(QLCDNumber::Filled);
    lcd.display(10);
    lcd.resize(220, 90);
    lcd.show();
    thread.start();

    return app.exec();
}

#include "main.moc"


а сигнал finished QThread сам генерит при завершении потока.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexondi
  опции профиля:
сообщение 11.6.2008, 23:03
Сообщение #5


Новичок


Группа: Новичок
Сообщений: 1
Регистрация: 11.6.2008
Пользователь №: 199

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




Репутация:   0  


Вообщем ситуация с потоками слотами в них такая.
Для того чтобы поток мог отрабатывать сигналы от других потоков (что одно и то же - обработка сигналов и слотов объектов в которых находятся объекты ) НЕОБХОДИМО:
1. в поток добавить QEventLoop - это основной механизм через который идет передача сообщений QEvent's а сигналы реализованы как раз с помощью них
зы можно сделать локальной переменной в методе run а можно и членом класса - на выбор
2. сам поток необходимо поместить сам в себя т.е. сделать в конструкторе this->moveToThread(this);
3. реализовать м методе run что-то вроде этого
void T_SlotThread::run( )
{
   fInnerLoop = new QEventLoop;
   fInnerLoop->exec();
}

ВСЕ!
Теперь все слоты данного потока (а также всех объектов для которых будет вызван метод moveToThread(ref_THREAD) будут выполняться в этом потоке а не в основном.
Сам поток тоже может иметь и сигналы и слоты

Сообщение отредактировал Litkevich Yuriy - 12.6.2008, 3:32
Причина редактирования: для наглядности используйте тэг code=cpp
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 16.6.2008, 9:59
Сообщение #6


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

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

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




Репутация:   17  


Есть небольшой вопросик на счет QEventLoop! Прочитал про этот класс в хелпе и не понял его предназначения, можете пояснить своими словами, пожалуйста? Предназначен обработки в цикле событий или что?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 16.6.2008, 11:01
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


Цитата(AD @ 16.6.2008, 13:59) *
Предназначен обработки в цикле событий или что?

Ну если всего лишь перевести вступление:
Цитата
The QEventLoop class provides a means of entering and leaving an event loop

то получится:
Цитата
QEventLoop класс предоставляет средства входа и выхода в цикл событий


читая далее:
Цитата
В любое время вы можете создать объект QEventLoop и вызвать exec() для него, чтобы запустить локальный цикл событий.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 16.6.2008, 11:18
Сообщение #8


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

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

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




Репутация:   17  


Цитата(Litkevich Yuriy @ 16.6.2008, 12:01) *
Ну если всего лишь перевести вступление:
Цитата
The QEventLoop class provides a means of entering and leaving an event loop

то получится:
Цитата
QEventLoop класс предоставляет средства входа и выхода в цикл событий


читая далее:
Цитата
В любое время вы можете создать объект QEventLoop и вызвать exec() для него, чтобы запустить локальный цикл событий.


Я не очень понимаю цели этого цикла событий! Зачем он нужен? Можно объяснить на том, примере, что приведен выше?
Перевод я догадался сделать! ;) :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
void*
  опции профиля:
сообщение 16.6.2008, 14:15
Сообщение #9


Программист-самоучка
***

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

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




Репутация:   3  


я особо не читал, но по моему мнению этот класс служит для организации циклов событий, управления ими, т.е. можно вообще например, выключить события и, например, при нажатии на клавишу ничего не будет происходить. Но это лишь мое мнение, точно не знаю
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 23.10.2019, 22:11