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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QueuedConnection  (Прочитано 6091 раз)
Fess
Гость
« : Июнь 02, 2011, 06:10 »

Извиняюсь за тупой вопрос, но все же.. Объясните пожалуйста, в чем магия?
Минимальный пример:
Код:
#include <QtGui/QApplication>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QDialog>

class Dialog : public QDialog {
Q_OBJECT

public:
explicit Dialog(QWidget *parent = 0)
: QDialog(parent)
{

}
};

class Tester : public QObject {
Q_OBJECT
protected:
int i;
QTimer timer;
public:
Tester(QObject* parent = NULL)
: QObject(parent)
, i(0)
{
timer.setInterval(3000);
connect(&timer,SIGNAL(timeout()),this,SLOT(RunDialog()),Qt::QueuedConnection);
timer.start();
}

public slots:
void RunDialog() {
qDebug()<<"run in "<<QThread::currentThreadId();
Dialog w;
w.setWindowTitle(QString("Dialog %1 from %2").arg(i++).arg(QString::number((long)QThread::currentThreadId(),16)));
w.exec();
qDebug()<<"Dialog \""<<w.windowTitle()<<"\" closed";
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
qDebug()<<"main thread "<<QThread::currentThreadId();
Tester tester;
return a.exec();
}

#include "main.moc"

Каждые 3 секунды посылается сигнал на создание нового диалога и проходит через event loop. Диалог запускается как модальный и по идее выполнение главного потока должно останавливаться пока он не будет закрыт и не будет получен результат от exec().
Но вместо этого постоянно создаются новые диалоги.
Если сделать соединение сигнал-слот DirectConnection, то в каждый момент может быть запущен только один диалог.
Я хочу понять в чем причина такого поведения при QueuedConnection.
« Последнее редактирование: Июнь 02, 2011, 07:29 от Fess » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Июнь 02, 2011, 06:43 »

Диалог запускается как модальный и по идее выполнение главного потока должно останавливаться пока он не будет закрыт и не будет получен результат от exec().
Поток у них один и тот же. Весь GUI живёт в одном потоке.
А разница, скорее всего в реализации QTimer. Для QTimer разница следующая: при прямом соединении он не выходит из QTimer::timerEvent, а так и стоит на emit timeout, а при соединении очереди - выходит.
Почему не программа не заходит повторно в timerEvent, если в предыдущий раз не вышла? Видимо есть в обработчике событий некоторая защита...
Записан
Fess
Гость
« Ответ #2 : Июнь 02, 2011, 07:29 »

QTimer здесь для примера. В моем случае сигналы приходили по сети из другого потока, но поведение аналогичное.
Мне интересно вот с этого момента:
Цитировать
Qt::QueuedConnection:
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
управление вернулось в event loop, заметило что пришел упакованный в событие сигнал, запустило слот. Слот управление не возвращает и главный поток должен ждать выхода из exec. Однако, события продолжают приходить и слот выполняется снова и снова.
Допустим, event loop работает в отдельном потоке, но слот-то каждый раз выполняется в одном и том же!
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #3 : Июнь 02, 2011, 07:54 »

Слот управление не возвращает и главный поток должен ждать выхода из exec.
Ну как вам объяснить? Ну нету там главного и неглавного потока. Весь гуй живёт в одном потоке, хоть 100500 модальных диалогов создайте. В модальном диалоге события обрабатываются, значит они обрабатываются и во всём потоке. Именно поэтому, скажем, неактивные (из-за модальности диалога) окна не перестают перерисовываться (то есть для них происходит paintEvent). Просто QEventLoop::ExcludeUserInputEvents в них не принимаются.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Июнь 02, 2011, 11:30 »

Модальность окна ни в коей мере не влияет на генерацию событий, но влияет на доставку некоторых.
« Последнее редактирование: Июнь 02, 2011, 11:32 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Июнь 02, 2011, 12:04 »

Если кратко то "Qt так работает"  Улыбающийся
С DirectConnection вызов слота происходит через QMetaObject::activate, который захватывает мутекс объекта, поэтому дальнейшие сигналы (посылаемые ему через direct) не проходят пока мутекс не освобожден. С QueuedConnection вызов идет через placeMetaCall, который такой блокировки не имеет.

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

Edit: насчет мутекса это я загнул  Улыбающийся Там проверяется через signal_begin_callback/signal_end_callback - но суть та же
« Последнее редактирование: Июнь 02, 2011, 12:21 от Igors » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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