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

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

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Потоки, сигналы, слоты и потенциальные касяки если связать все это?  (Прочитано 23732 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #30 : Январь 30, 2009, 13:29 »

но если пишу так:

объекты:

Код:
class A : public QObject
{
    Q_OBJECT
signals:
    void sgFromA();
public slots:
    void slotA() {
        qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
        emit sgFromA();
    }
private:

};

class B: public QObject
{
    Q_OBJECT
public slots:
    void slotB() {
        qWarning() << "B::slotB() -> TID = " << QThread::currentThreadId();
    }
private:
};

class ThA : public QThread
{
public:
    A *cA;
    ThA() { }
protected:
    void run() {
        qWarning() << "running ThA::run() -> TID = " << QThread::currentThreadId();
        cA = new A;
        forever {
            sleep(1);
            cA->slotA();
        }
    }
};

class ThB : public QThread
{
public:
    B *cB;
    ThB() { }
protected:
    void run() {
        qWarning() << "running ThB::run() -> TID = " << QThread::currentThreadId();
        cB = new B;
        exec();
    }
};

main

Код:
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    //qWarning() << "App TP:" << QThread::currentThread();
    qWarning() << "Application -> TID = " << QThread::currentThreadId();
    ThA *tA = new ThA;
    ThB *tB = new ThB;
    app.connect(tA->cA, SIGNAL(sgFromA()), tB->cB, SLOT(slotB()), Qt::QueuedConnection);
    tA->start();
    tB->start();
    return app.exec();
}

то консоль выводит :
Цитировать
Application -> TID =  0x864
running ThA::run() -> TID =  0x11c
running ThB::run() -> TID =  0x348
A::slotA() -> TID =  0x11c
A::slotA() -> TID =  0x11c
A::slotA() -> TID =  0x11c
A::slotA() -> TID =  0x11c
A::slotA() -> TID =  0x11c
A::slotA() -> TID =  0x11c
^C

т.е получается что не "ловится" или не емиттится сигнал A::sgFromA() слотом B::slotB() Грустный
Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #31 : Январь 30, 2009, 15:20 »

вроде получилось Улыбающийся

ab.h

Код:

#ifndef AB_H
#define AB_H
#include <QThread>
#include <QDebug>

class A : public QObject
{
    Q_OBJECT
signals:
    void sgFromA();
public slots:
    void slotA() {
        for (int i=0;i<5;++i) {
            qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
            emit sgFromA();
        }
        //forever {
        //    qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
        //    emit sgFromA();
        //}
    }
    void slotA2() {
        qWarning() << "A::slotA2() -> TID = " << QThread::currentThreadId();
    }
};

class B: public QObject
{
    Q_OBJECT
signals:
    void sgFromB();
public slots:
    void slotB() {
        qWarning() << "B::slotB() -> TID = " << QThread::currentThreadId();
        emit sgFromB();
    }
};

class ThA : public QThread
{
public:
    A *cA;
    ThA() { cA = new A; }
protected:
    void run() {
        qWarning() << "running ThA::run() -> TID = " << QThread::currentThreadId();
        cA->slotA();
        exec();
    }
};

class ThB : public QThread
{
public:
    B *cB;
    ThB() { cB = new B; }
protected:
    void run() {
        qWarning() << "running ThB::run() -> TID = " << QThread::currentThreadId();
        exec();
    }
};

#endif // AB_H

main.cpp

Код:
#include <QtCore>
#include <QCoreApplication>
#include <QDebug>


#include "ab.h"


int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    //qWarning() << "App TP:" << QThread::currentThread();
    qWarning() << "Application -> TID = " << QThread::currentThreadId();
    ThA *tA = new ThA;
    ThB *tB = new ThB;
    tB->cB->moveToThread(tB);
    tA->cA->moveToThread(tA);
    QObject::connect(tA->cA, SIGNAL(sgFromA()), tB->cB, SLOT(slotB()), Qt::QueuedConnection);
    QObject::connect(tB->cB, SIGNAL(sgFromB()), tA->cA, SLOT(slotA2()), Qt::QueuedConnection);
    tA->start();
    tB->start();
    return app.exec();
}

вывод:
Цитировать
Application -> TID =  0x830
running ThA::run() -> TID =  0xe4
running ThB::run() -> TID =  0x730
A::slotA() -> TID =  0xe4
A::slotA() -> TID =  0xe4
B::slotB() -> TID =  0x730
A::slotA() -> TID =  0xe4
B::slotB() -> TID =  0x730
A::slotA() -> TID =  0xe4
B::slotB() -> TID =  0x730
A::slotA() -> TID =  0xe4
B::slotB() -> TID =  0x730
A::slotA2() -> TID =  0xe4
B::slotB() -> TID =  0x730
A::slotA2() -> TID =  0xe4
A::slotA2() -> TID =  0xe4
A::slotA2() -> TID =  0xe4
A::slotA2() -> TID =  0xe4
^C

вроде все так как мне нужно - но я не уверен что это заработает, если в классе А написать так:
Код:
    void slotA() {
        //for (int i=0;i<5;++i) {
        //    qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
        //    emit sgFromA();
        //}
        forever {
            qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
            emit sgFromA();
        }
    }
Записан

ArchLinux x86_64 / Win10 64 bit
Dendy
Гость
« Ответ #32 : Январь 30, 2009, 16:18 »

Всё правильно, должно работать.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #33 : Февраль 02, 2009, 16:25 »

хм... сделал так:
Код:
    void slotA() {
        //for (int i=0;i<5;++i) {
        //    qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
        //    emit sgFromA();
        //}
        forever {
            qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
            emit sgFromA();
        }
    }

но почему-то память жутко утекает о_О . вроде ж в этом примере не создаются никакие объекты!
Записан

ArchLinux x86_64 / Win10 64 bit
Dendy
Гость
« Ответ #34 : Февраль 02, 2009, 16:37 »

В слоте остановлен цикл событий для потока А. События для него накапливаются, но никто их не обрабатывает.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #35 : Февраль 02, 2009, 16:42 »

Цитировать
В слоте остановлен цикл событий для потока А. События для него накапливаются, но никто их не обрабатывает.
1. хм... ткните пальцем Улыбающийся я не понял... яж нигде не останавливал цикл событий!
2. я ж слотом цепляюсь за сигнал.. т.е получается - обрабатываю!
« Последнее редактирование: Февраль 02, 2009, 16:56 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Dendy
Гость
« Ответ #36 : Февраль 02, 2009, 17:31 »

forever - это и есть остановка итерации. Причём без условия выхода из цикла, так вообще нельзя. Для этого потока всё остальное кроме этого цикла выполняться не будет.
Записан
BRE
Гость
« Ответ #37 : Февраль 02, 2009, 17:32 »

1. хм... ткните пальцем Улыбающийся я не понял... яж нигде не останавливал цикл событий!
Ты его не запускаешю.

Для начала обработки событий, в run() нужно выполнить QThread::exec().

Код
C++ (Qt)
void MyThread::run()
{
// Создали нужные объекты.
// Приконектились куда надо.
// ...
exec(); // Запустили цикл обработки событий
}
 
« Последнее редактирование: Февраль 02, 2009, 17:35 от BRE » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #38 : Февраль 02, 2009, 18:27 »

Цитировать
Для начала обработки событий, в run() нужно выполнить QThread::exec().
ну у меня ж это есть!
Код:
 
void run() {
        qWarning() << "running ThA::run() -> TID = " << QThread::currentThreadId();
        cA->slotA();
        exec();
    }

Цитировать
forever - это и есть остановка итерации. Причём без условия выхода из цикла, так вообще нельзя. Для этого потока всё остальное кроме этого цикла выполняться не будет.
это  получается что если в A::slotA() будет вечный цикл, то до exec() очередь не дойдет?

-----

хм... если так, то получается вообще замкнутый круг.. Грустный , т.е нереально реализоватьвообще вот эту идею:
1. Имеется подсистема А в приложении (которая является отдельным потоком) и которая "вечно" в цикле  анализирует некий массив данных....
суть анализа заключается в получении данных (опросе) из неких удаленных девайсов и сравнении полученных значений с предыдущим шагом... и если значение отличается - то выдать сигнал! (т.е выдать сигнал, если данные изменились)
2, Имеется подсистема В в приложении (которая тоже является потоком) и которая "отлавливает" сигнал, полученный от подсистемы А и выполняет свой алгоритм!

Необходимо, чтобы :
1. главный поток приложения был  - отдельно
2. поток подсистемы А выполнялся - отдельно (и все методы класса А выполнялись в этом потоке)
3. поток подсистемы В выполнялся - отдельно (и все методы класса В выполнялись в этом потоке)
т.е как минимум иметь три "вечно" работающих потока!

я что-то уже растерян, не представляю как это уже реализовать!
Записан

ArchLinux x86_64 / Win10 64 bit
ритт
Гость
« Ответ #39 : Февраль 02, 2009, 18:37 »

зачем вечный цикл выполняется в _слоте_ объекта А? если нужен вечный цикл и одновременно необходимы слоты в некотором потоке, используй таймер. если слоты не нужны, замени петлю событий (exec()) в этом потоке на цикл с условием выхода (при останове/разрушении потока и т.п.)
Записан
BRE
Гость
« Ответ #40 : Февраль 02, 2009, 19:11 »

я что-то уже растерян, не представляю как это уже реализовать!

Вот смотри вариант с таймером:
Код
C++ (Qt)
void ThreadA::run()
{
QTimer timer;
connect( &timer, SIGNAL( timeout() ), SLOT( checkData() ) );
// Раз в секунду запускаем проверку данных
timer.start( 1000 );
 
exec();
}
 
void ThreadA::checkData()
{
// Проверили и при необходимости
emit dataCahnged(); // отправляем сигнал
}
 
 
void ThreadB::run()
{
connect( threadA, SIGNAL( dataChanged() ), SLOT( processData() ) );
 
exec();
}
 
void ThreadB::processData()
{
// Получили сигнал от А
// Забрали данные
// Обработали их
}
 

Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #41 : Февраль 02, 2009, 19:29 »

вот, переписал по-другому:

ab.h
Код:

#ifndef AB_H
#define AB_H
#include <QThread>
#include <QDebug>
#include <QTimer>

class A : public QObject
{
    Q_OBJECT
signals:
    void sgFromA();
public slots:
    void slotA() {//слот где инициализируем таймер
        qWarning() << "A::slotA() -> TID = " << QThread::currentThreadId();
        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(slotA1()));
        timer->start(10);
    }
    void slotA1() {//слот где по таймеру выполняем емиттинг сигнала
            qWarning() << "A::slotA1() -> TID = " << QThread::currentThreadId();
            emit sgFromA();
    }
    void slotA2() {//слот который выполняется при выдаче классом В сигнала
        qWarning() << "A::slotA2() -> TID = " << QThread::currentThreadId();
    }
};

class B: public QObject
{
    Q_OBJECT
signals:
    void sgFromB();
public slots:
    void slotB() {//слот, который выполняется при выдаче классом А сигнала
        qWarning() << "B::slotB() -> TID = " << QThread::currentThreadId();
        emit sgFromB();
    }
};

class ThA : public QThread
{
public:
    A *cA;
    ThA() { cA = new A; }
protected:
    void run() {
        qWarning() << "running ThA::run() -> TID = " << QThread::currentThreadId();
        cA->slotA();
        exec();
    }
};

class ThB : public QThread
{
public:
    B *cB;
    ThB() { cB = new B; }
protected:
    void run() {
        qWarning() << "running ThB::run() -> TID = " << QThread::currentThreadId();
        exec();
    }
};
#endif // AB_H

так правильно (корректно) ?

Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #42 : Февраль 02, 2009, 19:36 »

2 Константин & 2 ВRE & 2 Dendy, спасибки за наводку ! Улыбающийся

щас проверил в Linux с таймером в 10мс - вроде не кушает память.. завтра проверю в WinXP Улыбающийся

ЗЫ: за то что я не корректно в примерах высвобождаю указатели - просьба не бить жестко, т.к примерчики чисто теоретическо-практического-тестового плана!
Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


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