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(), но с ней ничего вообще не получается, в слот не попадает ни один поток...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
sploid
  опции профиля:
сообщение 4.6.2008, 14:21
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 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
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 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
Сообщение #4


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

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

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




Репутация:   17  


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

Сообщений в этой теме


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


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




RSS Текстовая версия Сейчас: 4.12.2024, 8:57