Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие _ Посылка сигнала из дополнительного потока в главный

Автор: AD 4.6.2009, 10:05

Есть дополнительный поток, в котором происходит циклическое перемещение прожектора в одной из плоскостей. В этом потоке есть переменная int number_rotate, которая отвечает за количество вращений в цикле. После каждого перемещения она уменьшает свое значение.
Как мне корректно отправить сигнал о том, что переменная изменила значение? И как в основном потоке его поймать?

/// Класс потока - вращение вокруг вертикальной оси заданное количество раз
class HorizontalRotation: public QThread
{
    Q_OBJECT

/// есть и другие переменные и функции конечно же
private:
    int number_rotate;                            ///< количество вращений

protected:
    virtual void run();
};


/// Запуск потока вращения в горизонтальной плоскости
void HorizontalRotation::run()
{
    if(!number_rotate) return;

    int geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    int azimuth = 172 * 10;                                ///< правый предел прожектора
    if(geted_azimuth < ((172. - 1.5) * 10) || geted_azimuth > ((172. + 1.5) * 10))
    {
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);        ///< перевод в этот предел прожектора
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
    }
    readAzimuth(geted_azimuth, 172.);

    /// внешний цикл по количеству перемещений
    const int number_cycles = number_rotate;
    for(register int i=0; i<number_cycles; ++i)
    {
        azimuth = -172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, -172.);

        azimuth = 172 * 10;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAzimuth(geted_azimuth, 172.);
        --number_rotate;
    }

    if(!number_rotate) quit();
}


--number_rotate;
- вот строчка изменения значения переменной.

Автор: SABROG 4.6.2009, 10:37

Законнектить сигнал из потока со слотом из главного потока как Qt::QueuedConnection. Потом emit этого сигнала с твоим параметром.

Правда я не помню, connect вроде бы делать надо в run(), а не в главном потоке. Ну и без exec() в конце run() не обойтись. Может еще поможет QMetaObject::invoke(), чтобы поставить сигнал в очередь насильно.

Автор: igor_bogomolov 4.6.2009, 11:00

Цитата(SABROG @ 4.6.2009, 11:37) *
Правда я не помню, connect вроде бы делать надо в run(), а не в главном потоке. Ну и без exec() в конце run() не обойтись. Может еще поможет QMetaObject::invoke(), чтобы поставить сигнал в очередь насильно.
exec() в данном случае не нужен. Да и коннетк делать там, где создается экземпляр класса HorizontalRotation.

Цитата(SABROG @ 4.6.2009, 11:37) *
Законнектить сигнал из потока со слотом из главного потока как Qt::QueuedConnection. Потом emit этого сигнала с твоим параметром.
Более чем достаточно. Qt::QueuedConnection необязателен, он по идее должен выставиться по умолчанию.

Автор: AD 4.6.2009, 11:03

Хочу уточнить:
сигнал определить в дополнительном потоке, а слот создать в главном? Emit делать в слоте главного потока? А коннект в функции run дополнительного? Все так?

Автор: igor_bogomolov 4.6.2009, 11:18

Цитата(AD @ 4.6.2009, 12:03) *
сигнал определить в дополнительном потоке, а слот создать в главном? Emit делать в слоте главного потока? А коннект в функции run дополнительного? Все так?
Нет.

псевдокод
class HorizontalRotation: public QThread
{
    Q_OBJECT
    int number_rotate;

protected:
    virtual void run();

signals:
    void displayNR(int);
};

void HorizontalRotation::run()
{
    ....
    emit displayNR(number_rotate); \\ где то в потоке
    ...
}


class Form : public QMainWindow, public Ui::MainWindow
{
    Q_OBJECT

    HorizontalRotation horizontalRotation;
    ....
private slots:
    void displayNR(int number);
    ....
}


Form::Form(QWidget *parent) : QMainWindow(parent)
{
    ....
    connect(&horizontalRotation, SIGNAL(displayNR(int)), SLOT(displayNR(int)));
    ....
}
    
void Form::displayNR(int number)
{
     \\ выполняешь необходимые действия
}

Автор: Litkevich Yuriy 4.6.2009, 14:46

Цитата(AD @ 4.6.2009, 15:03) *
сигнал определить в дополнительном потоке, а слот создать в главном? Emit делать в слоте главного потока?
а в какую сторону посылать собираешь так и делай, просто забудь про потоки, чтобы они тебя не отвелекали.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)