Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сигнал, который был послан до connect, Что происходит с сообщением? 
V
    Опции темы
null56
Дата 4.2.2009, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



В общем меня интересует, есть ли в Qt очередь "отложенных" сообщений?
Допустим, у меня есть Object_1, который находится в дочернем потоке ...
Я связал его с обработчиком во вторичной ните и послал сигнал из первичной нити.... 
Что получилось:
если сигнал успевал связываться со слотом во вторичной ните и эта нить успевала входить в eventloop, то слот, как надо отрабатывался в дочерней ните, если нет (опробовал с sleep), то сигнал никогда так и не доходил до адресата...

Вопрос:
1) Если не запущен eventloop, то посланный сигнал уничтожается?
2) Если через сигнал я посылаю адрес динамически созданного объекта emit mySignal(MyObject * pObject), то получается утечка, если сигнал где - то затерялся?

Получается, чтобы сохранить сигнал, мало связать его с connect, необходимо еще успеть запустить exec() ?

Для наглядности, если сложно пишу, приведу пример:

Класс нити h
Код

class Thread : public QThread
{
    Q_OBJECT

    public:
        Thread(MyClass * pMyClass);
        void Value2Thread(int i);
    
    protected:
        void run();

    private:
        MyClass * myClass;
};


Класс нити cpp
Код

Thread::Thread(MyClass * pMyClass)
{
    myClass = pMyClass;
}

void Thread :: run()
{
    qDebug("run thread: %d", currentThreadId());
    Action action;
    
    connect(myClass, SIGNAL(sendValue(int)), &action, SLOT(myValueSlot(int)));
//    sleep ( 3) ; // КЛЮЧЕВОЕ МЕСТО, ЕСЛИ РАСКОММЕНТИТЬ, ЧТО ПЕРВИЧНАЯ ОБГОНИТ ВТОРИЧНЫЙ
    exec();
}

void Thread :: Value2Thread(int i)
{
    myClass->emitSignal(i);
}


класс MyClass h
Код

class MyClass : public QObject
{
    Q_OBJECT

    public:
        MyClass();
        void emitSignal(int i) {emit sendValue(i);}

    signals :
        void sendValue(int i);
};


класс обработчик
Код

class Action : public QObject
{
    Q_OBJECT

    public:
        Action();
        ~Action();

    public slots:
        void myValueSlot(int i) {qDebug("My value %d in slot thread: %d", i, QThread :: currentThreadId ());} // вынес из спп
};


Собственно функция main.cpp
Код

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug("Main thread: %d", QThread :: currentThreadId());
    Thread thread(new MyClass);
    thread.start();
    sleep ( 3) ; // ПОДОЖДАТЬ, ЧТОБЫ НАВЕРНЯКА УСПЕЛ
    qDebug("Before emit");
    thread.Value2Thread(5); // ПОШЛЕМ СИГНАЛ ДОЧЕРНЕМУ ОБРАБОТЧИКУ
    return a.exec();
}

PM MAIL   Вверх
null56
Дата 4.2.2009, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



По поводу exec - это я погорячился... если связываю connect, то даже незапущенный exec сохраняет очередь сигналов...
Просто в моем примере получалось так, что connect происходил после emit, что естественно уничтожало сообщения....
Это я увидел на отладочной печати
PM MAIL   Вверх
Elfebet
Дата 4.2.2009, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 545
Регистрация: 15.5.2006
Где: Украина. Запорожь е.

Репутация: 5
Всего: 14



очень запутано написал и невнятно, попытаюсь ответить
по порядку отвечу, могу ошибаться
Цитата(null56 @  4.2.2009,  13:39 Найти цитируемый пост)
В общем меня интересует, есть ли в Qt очередь "отложенных" сообщений?

в принципи да
Цитата(null56 @  4.2.2009,  13:39 Найти цитируемый пост)
Если не запущен eventloop, то посланный сигнал уничтожается?

никак нет, сигнал уничтожить можно только через disconnect или если указатель обьекта уже невалидный


Цитата(null56 @  4.2.2009,  13:39 Найти цитируемый пост)
Если через сигнал я посылаю адрес динамически созданного объекта emit mySignal(MyObject * pObject), то получается утечка, если сигнал где - то затерялся?

сигнал не затеряется, сигнал - он только посылает сигнал и все, а прийдет он слот или нет это уже зависит от того передается такой же параметр в слот или нет 
Код

connect(this, SIGNAL( mySignal(myObject*) ), object, mySlot(myObject*)) // параметр из сигнала передастся в слот
connect(this, SIGNAL( mySignal(myObject*) ), object, mySlot()) // параметр из сигнала НЕ передастся в слот


если ты имеш ввиду 
Код

    QPushButton *btn1 = new QPushButton("1", this);
    QPushButton *btn2 = new QPushButton("2", this);
    connect(btn1, SIGNAL(clicked()), this, SLOT(click1()));
    btn1 = btn2;
    connect(btn1, SIGNAL(clicked()), this, SLOT(click2()));

тогда сдесь для btn1 сработает click1(), для btn2 сработает click2() так как "connect" копирует указатель
Цитата(null56 @  4.2.2009,  13:39 Найти цитируемый пост)
Получается, чтобы сохранить сигнал, мало связать его с connect, необходимо еще успеть запустить exec() ?

exec() сдесь вообще не в тему



чтоб хорошо понять как работает connect посмотри в ассистенте про "connectionType"
цитирую
Цитата

Qt::DirectConnection - When emitted, the signal is immediately delivered to the slot.
Qt::QueuedConnection - When emitted, the signal is queued until the event loop is able to deliver it to the slot.
Qt::BlockingQueuedConnection - Same as QueuedConnection, except that the current thread blocks until the slot has been delivered. This connection type should only be used for receivers in a different thread. Note that misuse of this type can lead to dead locks in your application.
Qt::AutoConnection - If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.

по умолчанию используеться Qt::AutoCompatConnection

Это сообщение отредактировал(а) Elfebet - 4.2.2009, 18:14


--------------------
Программист не должен всё знать... он должен знать где можно посмотреть
PM MAIL ICQ GTalk   Вверх
null56
Дата 4.2.2009, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Спасибо большое... так намного понятнее....

если сначала произошел emit, а лишь потом connect, сигнал теряется....  верно?
PM MAIL   Вверх
SABROG
Дата 4.2.2009, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(null56 @  4.2.2009,  18:52 Найти цитируемый пост)
если сначала произошел emit, а лишь потом connect, сигнал теряется....  верно? 

Надо экспериментировать. Но мне кажется что, если сигнал обычный (не Qt::Queuedconnection) и на него нет коннекта, то он не вызывается и просто пропадает. Если все-таки это очередный сигнал и коннект произойдет до выхода в eventloop, то может сработать, это если где-то в недрах не идет проверка на существование коннекта перед добавлением в очередь.

Чтобы знать наверняка, возможно надо лезть в исходники QEventLoop/QEventDispatcher/QObject'a.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
kuzulis
Дата 5.2.2009, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



2 null56, 

посмотри вот эту темку http://www.prog.org.ru/topic_8455_30.html

там попробуй в коде ab.h по очереди заккоментировать строчки:
Выделить всёкод C++
1:
2:
    
    tB->cB->moveToThread(tB);
    tA->cA->moveToThread(tA);


и посмотри в чем разница при выводе результатов smile

и вообще почитай эту темку с начала, там вроде то что тебе нужно!

Добавлено через 2 минуты и 5 секунд
блин.. как отредактировать свой пост? smile

Добавлено через 8 минут и 7 секунд
т.е. не в ab.h а в main.cpp нужно закомментировать по очереди:
Код

    tB->cB->moveToThread(tB);
    tA->cA->moveToThread(tA);

PM MAIL   Вверх
null56
Дата 5.2.2009, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Цитата(SABROG @ 4.2.2009,  20:22)
Надо экспериментировать. 
Чтобы знать наверняка, возможно надо лезть в исходники QEventLoop/QEventDispatcher/QObject'a.

Нет, обычными средствами сигнал теряется, вопрос в том, как можно проверить, есть ли конннект хоть к чему -  то.... вот примерчик с одним потоком

main.cpp
Код

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SigSlot b, c;
    b.emitSignal();
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::DirectConnection);
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::QueuedConnection);
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::BlockingQueuedConnection);
    QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::AutoConnection);
    return a.exec();
}


Код

class SigSlot : public QObject
{
    Q_OBJECT
public:
    SigSlot();
    void emitSignal() {    qDebug("New signal");    emit newSignal(); }
signals:
    void newSignal();

public slots:
    void onNewSignal() {qDebug("MySlot");}
};


Сейчас посмотрю о чем писал kuzulis

Это сообщение отредактировал(а) null56 - 5.2.2009, 10:36
PM MAIL   Вверх
null56
Дата 5.2.2009, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Цитата(kuzulis @ 5.2.2009,  08:50)
и вообще почитай эту темку с начала, там вроде то что тебе нужно!

ну... я вообще не понял, как тот пост относится к нашей теме (...
если речь идет о функции moveToThread или как сделать так, чтобы слоты отрабатывались в дочернем потоке, то я и SABROG в параллельной темке полностью разобрали этот вопрос и альтернативные пути решения этой проблемы
http://forum.vingrad.ru/forum/topic-241300...qsslsocket.html
и убрав moveToThread в твоем примере, понятное дело слоты будут в иметь первичный threadId....

Но здесь меня интересует другое....

Это сообщение отредактировал(а) null56 - 5.2.2009, 11:07
PM MAIL   Вверх
Elfebet
Дата 5.2.2009, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 545
Регистрация: 15.5.2006
Где: Украина. Запорожь е.

Репутация: 5
Всего: 14



ну из твоего примера все очевидно!
как можно поймать сигнал если его непосылали? 
ты сначала делаеш
Код
   b.emitSignal(); 

а потом
Код

    QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::AutoConnection);

и ждеш результата ?

нужно наоборот, соединить а потом послать сигнал. это ж очевидно
Код

    QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::AutoConnection);
   b.emitSignal();





--------------------
Программист не должен всё знать... он должен знать где можно посмотреть
PM MAIL ICQ GTalk   Вверх
kuzulis
Дата 5.2.2009, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



smile

упс.. чото и так не работает:

Код

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SigSlot b, c;
    QTimer *timer = new QTimer();
    QObject::connect(timer, SIGNAL(timeout()), &b, SLOT(emitSignal()), Qt::AutoConnection);
    timer->start(10);
    //b.emitSignal();
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::DirectConnection);
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::QueuedConnection);
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::BlockingQueuedConnection);
    //QObject :: connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()), Qt::AutoConnection);
    return a.exec();
}

PM MAIL   Вверх
Elfebet
Дата 5.2.2009, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 545
Регистрация: 15.5.2006
Где: Украина. Запорожь е.

Репутация: 5
Всего: 14



kuzulis, так оно и не сработает, ты ж закоментил b.emitSignal();
Народ все довольно просто и логично
Код

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    SigSlot b, c;
    b.emitSignal(); // слот не сработает, так как ничего неизвесно о слоте
    QObject::connect(&b, SIGNAL(newSignal()), &c, SLOT(onNewSignal()));
    b.emitSignal(); // сработает, так как соединили со слотом
    return a.exec();
}




--------------------
Программист не должен всё знать... он должен знать где можно посмотреть
PM MAIL ICQ GTalk   Вверх
null56
Дата 5.2.2009, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Elfebet, это я понимаю.... вопрос немного в другом стоит уже....
Можно ли узнать, имеет ли подсоединенные слоты, тот или иной сигнал из метаобъектной модели qt?

Код

и ждеш результата ?

Это был пример для наглядности, задача изначально сводилась к другому.... если ты посмотришь первое мое сообщение, то там в коде все понятно, почему тема начата....

У меня в дочернем потоке получалось так, что объект не успевал соединиться сигналами с обработчиком в дочернем потоке до того, как приходил сигнал и он пропадал

Это сообщение отредактировал(а) null56 - 5.2.2009, 11:58
PM MAIL   Вверх
kuzulis
Дата 5.2.2009, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



2 null56, я ничего не комментил.. smile
вот в коннекте этот слот должен выполняться же:
Код

QObject::connect(timer, SIGNAL(timeout()), &b, SLOT(emitSignal()), Qt::AutoConnection);

т.е 
&b, SLOT(emitSignal())

!!!!

Добавлено через 1 минуту и 6 секунд
т.е при срабатывании таймера должен выполняться слот b::emitSignal() в котором и происходит емиттинье и вывод в консоль!
PM MAIL   Вверх
null56
Дата 5.2.2009, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Цитата(kuzulis @ 5.2.2009,  12:03)
2 null56, я ничего не комментил.. smile
вот в коннекте этот слот должен выполняться же:
Код

QObject::connect(timer, SIGNAL(timeout()), &b, SLOT(emitSignal()), Qt::AutoConnection);

т.е 
&b, SLOT(emitSignal())

!!!!

Добавлено @ 12:04
т.е при срабатывании таймера должен выполняться слот b::emitSignal() в котором и происходит емиттинье и вывод в консоль!

void emitSignal() - ЭТО НЕ СЛОТ и в консоли тебе должны написать, что соединение не прошло!!!

Добавлено через 3 минуты и 43 секунды
в класс SigSlot сделай и пересобери и посмотри на результат
Код

public slots:
    void onNewSignal();
    void emitSignal();

PM MAIL   Вверх
Elfebet
Дата 5.2.2009, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 545
Регистрация: 15.5.2006
Где: Украина. Запорожь е.

Репутация: 5
Всего: 14



все понятно, перечитал 1 пост и все дело в thread.start();
thread.start(); - запускает поток и емит сигнала происходит первее чем соединение  сигнал-слот - впринципи это понятно почему.
Нормальное решение - прописывать "connect" в конструкторе класса thread
Код

Thread::Thread(MyClass * pMyClass)
{
    myClass = pMyClass;
    Action action;
    connect(myClass, SIGNAL(sendValue(int)), &action, SLOT(myValueSlot(int)));
}

void Thread :: run()
{
    qDebug("run thread: %d", currentThreadId());
}

void Thread :: Value2Thread(int i)
{
    myClass->emitSignal(i);
}

так будет правильнее всего


--------------------
Программист не должен всё знать... он должен знать где можно посмотреть
PM MAIL ICQ GTalk   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0635 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.