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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: moveToThread(), exec(),Qt::DirectConnection, Qt::QueueConnection  (Прочитано 10640 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« : Май 26, 2016, 11:35 »

Простите, что задаю идиотские вопросы  Улыбающийся, но еще раз Улыбающийся
1.
Код:
    moveToThread()

Хотелось уточнить можно ли делать так:

Код
C++ (Qt)
Thread::Thread(QObject *parent):
            QThread(parent)
{
   moveToThread(this);
}
 
void Thread::run()
{
 
  exec();
}
 

Если да, то получается что объект потока у нас перемещается в поток, который описывается в run.

2.В контексте какого потока будет обрабатываться

Код:
Thread::slot_time_out

, если не указывать Qt::ConnectionType Непонимающий
Если я правильно понимаю в потоке, в котором был создан объект класса Thread.
Т.е автоматически получается
Код:
Qt::QueueConnection
.
Если неправ то поправьте.

Код
C++ (Qt)
Thread::Thread(QObject*parent):
      QThread(parent)
{
 
}
 
void Thread::run()
{
  QTimer *timer = new QTimer();
 
  connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out()));
 
  timer->start(500);
  exec();
}
 
void Thread::slot_time_out()
{
//
}
 

можно ли делать так???

Код:
connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out()),Qt::DirectConnection);

Если, да то тогда
Код:
Thread::slot_time_out()
будет обрабатываться в контексте потока Thread  и
надо мьютексировать поля класса Thread, так как он создан в основном потоке(в другом).

Если я не прав то поправьте и сильно не пинайте, пожалуйста Улыбающийся
« Последнее редактирование: Май 26, 2016, 12:21 от demaker » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Май 26, 2016, 12:36 »

Здесь Вы напоролись на исключение: события таймера должны приниматься именно в том потоке где он создан (Thread), а значит надо добавить moveToThread(this) или, как рекомендует теория, сделать это извне.

"объект перемешается в поток", "в контексте потока" - такие мутно-неудачные термины/выражения капитально запутывают. В действительности все очень просто. Разберемся как срабатывает Qt::AutoConnection. Допустим мы создали какой-то коннект
Код:
QObject::connect(src, SIGNAL(itemChanged(int)), dst, SLOT(itemChanged(int))); // Qt::AutoConnection
При испускании сигнала текущая нитка сравнивается с dst->thread(). Если они равны - прямой вызов (DirectConnection). Если нет то  QueuedConnection, сигнал помещается в очередь EventLoop той нитки (dst->thread()), и слот будет вызван при извлечении этого события и выполнен в потоке thread(). Конечно этот EventLoop должен быть запущен (QThread::exec())

Конструктор QObject устанавливает начальное значение thread() на текущую нитку (где выполняется код конструктора). Ну и, как Вы уже догадались, именно пресловутый moveToThread пере-устанавливает тот самый указатель что возвращает thread(). Хз почему это называют довольно нелепо "перемещение"(?), или, еще лучше, "объект живет в потоке"  Улыбающийся
« Последнее редактирование: Май 26, 2016, 14:13 от Igors » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #2 : Май 26, 2016, 13:06 »

Здесь Вы напоролись на исключение: события таймера должны приниматься именно в том потоке где он создан (Thread), а значит надо добавить moveToThread(this) или, как рекомендует теория, сделать это извне.
)

Что значит извне???

Есть книга "Qt4 на примерах" автор Юрий Земсков.
Есть пример кода Эхо-Сервера:
Код
C++ (Qt)
EchoThread::EchoThread(int socketDescriptor,QObject*parent = 0):
                QThread(parent),m_SocketDescriptor(socketDescriptor)
{
 
}
 
void EchoThread::run()
{
 m_client = new QTcpSocket();
 ...
 connect(m_client,SIGNAL(readyRead()),this,SLOT(onRead),Qt::DirectConnection);
 exec();
}
 
void EchoThread::onRead()
{
QByteArray block = m_client->readAll;
}
 

1. разве можно использовать здесь Qt::DirectConnection???
2. почему m_client не защищают мьютексами???

В приложенном файле скан странницы.
« Последнее редактирование: Май 26, 2016, 13:23 от demaker » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #3 : Май 26, 2016, 13:36 »

Есть книга "Qt4 на примерах" автор Юрий Земсков.
Это потому что Юра не знал как сделать правильно, поэтому он руками прописывал тип коннекта, что бы слоты вызывались в контексте нужной нитки. Улыбающийся
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #4 : Май 26, 2016, 13:44 »

Есть книга "Qt4 на примерах" автор Юрий Земсков.
Это потому что Юра не знал как сделать правильно, поэтому он руками прописывал тип коннекта, что бы слоты вызывались в контексте нужной нитки. Улыбающийся

Т.е здесь нужен DirectConnection чтобы обрабатывать непосредственно слот в созданном потоке. Т.к объект нитки создан в основном. И если бы не было DirectConnection, то connect был бы автоматически Qt::QueueConnection. Так получается???

А если бы мы добавили
Код:
moveToThread(this)
 в конструктор EchoThread то DirectConnection можно было бы не писать. Я правильно Вас понимаю???

Да и в коде
Код
C++ (Qt)
Thread::Thread(QObject*parent):
      QThread(parent)
{
 
}
 
void Thread::run()
{
  QTimer *timer = new QTimer();
 
  connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out())); //тип Qt::DirectConnection указывать
                                                                                          //или не надо???  
 
  timer->start(500);
  exec();
}
 
void Thread::slot_time_out()
{
//
}
 

« Последнее редактирование: Май 26, 2016, 14:06 от demaker » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #5 : Май 26, 2016, 14:02 »

Т.е здесь нужен DirectConnection чтобы обрабатывать непосредственно слот в созданном потоке. Т.к объект нитки создан в основном. И если бы не было DirectConnection, то connect был бы автоматически Qt::QueueConnection. Так получается???
Да. Объект класса QThread и объекты созданные в его методе run имеют разные контексты, поэтому был би применен тип QueueConnection.

А если бы мы добавили
Код:
moveToThread(this)
 в конструктор EchoThread то DirectConnection можно было бы не писать. Я правильно Вас понимаю???
Да.
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #6 : Май 26, 2016, 14:08 »

Да и в коде
Код
C++ (Qt)
Thread::Thread(QObject*parent):
      QThread(parent)
{
 
}
 
void Thread::run()
{
  QTimer *timer = new QTimer();
 
  connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out())); //тип Qt::DirectConnection указывать
                                                                                          //или не надо???  
 
  timer->start(500);
  exec();
}
 
void Thread::slot_time_out()
{
//
}
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #7 : Май 26, 2016, 14:19 »

Да и в коде
Если вы объект Thread перенесете в контекст нового потока через moveToThread( this ), то не надо указывать.
Контекст у объекта получателя (Thread) и отправителя (таймер) будут одинаковы и DirectConnection будет применяться по умолчанию.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Май 26, 2016, 14:21 »

Код
C++ (Qt)
  connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out())); //тип Qt::DirectConnection указывать
                                                                                          //или не надо???  
 
Конкретно для сигнала таймера - без разницы, это не поможет если this->thread() != this, а иначе и так Direct
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #9 : Май 26, 2016, 14:29 »

А moveToThread() это опасно или нет???

И еще, если в конструкторе Thread не делать
Код:
moveToThread(this)
и у класса есть поля, то их желательно мьютексировать, так как они могут использоваться и главном потоке. Правильно???
« Последнее редактирование: Май 26, 2016, 14:32 от demaker » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #10 : Май 26, 2016, 14:31 »

А moveToThread() это опасно или нет???
Вы изменяете одну переменную, значение которой нужно для определения типа коннекта. Не знаю насколько для вас это опасно. Улыбающийся
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #11 : Май 26, 2016, 14:37 »

Код
C++ (Qt)
  connection(timer,SIGNAL(timeOut()),this,SLOT(slot_time_out())); //тип Qt::DirectConnection указывать
                                                                                          //или не надо???  
 
Конкретно для сигнала таймера - без разницы, это не поможет если this->thread() != this, а иначе и так Direct

Ну да в том случае в котором я описал ниже this->thread() != this и если я хочу в этом потоке обрабатывать сигнал от таймера в этом потоке, то надо писать Qt::DirectConnection. Или нет???
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #12 : Май 26, 2016, 14:49 »

А moveToThread() это опасно или нет???
Вы изменяете одну переменную, значение которой нужно для определения типа коннекта. Не знаю насколько для вас это опасно. Улыбающийся

moveToThread изменяет thread() и тем самым объект перемещается в другой поток. Так???
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Май 26, 2016, 15:04 »

moveToThread изменяет thread() и тем самым объект перемещается в другой поток. Так???
Никто никуда не "перемешается", меняется поле объекта которое задает из какого EventLoop он будет получать сигналы с QueuedConnection
Цитировать
- В вашу деревню провели электричество, керосиновые лампы больше не нужны, просто вот тут включаете - и свет горит! Все поняли?

- Да, все ясно! А куда керосин заливать ??
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 960


Просмотр профиля
« Ответ #14 : Май 26, 2016, 15:07 »

moveToThread изменяет thread() и тем самым объект перемещается в другой поток. Так???
Никто никуда не "перемешается", меняется поле объекта которое задает из какого EventLoop он будет получать сигналы с QueuedConnection
Цитировать
- В вашу деревню провели электричество, керосиновые лампы больше не нужны, просто вот тут включаете - и свет горит! Все поняли?

- Да, все ясно! А куда керосин заливать ??

 Веселый Веселый Веселый Смеющийся Смеющийся Смеющийся Смеющийся

Теперь ясно Улыбающийся Спасибо большое за разъяснения!

Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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