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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Connect и его разновидности  (Прочитано 6340 раз)
fuCtor
Гость
« : Апрель 06, 2009, 16:42 »

Люди добрые объясните пожалуйста в чем различие в процессе выполнения конектов:
  • QueuedConnection
  • BlockingQueuedConnection
Судя по документации:
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

Т.е. при выполнении конекта с блокированием потока из которого был произведен вызов. Но при выполнении всеравно сначала выполняется emit сигнала, invokeMethod и return, а только затем собственно связанный слот, т.е. поток не блокируется. Или я что-то не так понял?

Суть проблемы почему стало это критично, так это наверно извращенный случай, когда сигнал возвращает значение. При DirectConnection все нормально работает, пока вызывающих потоков не больше одного. Когда потоков уже два и более постоянно валится эксепшн. Попытка обвязать все вызовы мьютексами не помогла. Может есть какие решения?
Или как еще можно реализовать локальную комутацию нескольких потоков с объектом из главного, не перетаскивать же его каждый раз в выполняемый поток для этого, хотя чем не способ )
Записан
whirlwind
Гость
« Ответ #1 : Апрель 06, 2009, 22:41 »

в Signals and Slots написано

Цитировать
Execution of the code following the emit statement will occur once all slots have returned. The situation is slightly different when using queued connections; in such a case, the code following the emit keyword will continue immediately, and the slots will be executed later.

т.е. разница как раз в том, что в одном случае поток, из которого пошел вызов будет заблокирован, а в другом -- нет.

Суть проблемы почему стало это критично, так это наверно извращенный случай, когда сигнал возвращает значение.
сигнал не может возвращать значение, об этом сказано там же, в Signals and slots. Это противоречит здравому смыслу: что возвратится, после того, как сработают подряд несколько слотов?
Записан
Sergeich
Гость
« Ответ #2 : Апрель 06, 2009, 23:38 »

Qt::BlockingQueuedConnection работает приблизительно так: объект, эмитирующий сигнал пробегается по списку слотов или сигналов, соединенных с данным, для каждого ждущего этого сигнала объекта, в очередь событий нитки, который этот объект принадлежит, добавляется событие QEvent::MetaCall, после чего выполнение потока, в котором эмитируется сигнал, приостанавливается до тех пор, пока не завершится обработка всех событий QEvent::MetaCall, инициированных данным сигналом.
Если объект, вызвавший сигнал и его получатель принадлежат одной нитке - будет дедлок => надо проверять принадлежность объектов к разным ниткам перед вызовом connect c данным параметром.
Хотя эта фича довольно удобна в некоторых случаях, юзать ее надо с большой осторожностью. Если можно обойтись без нее - лучше не юзать.
Из собственного опыта: я юзал этот коннект, когда в дополнительной счетной нитке, в которой не было событийного цикла,  возникала какая-нибудь критическая ситуация - например, заканчивалось место на диске - и надо было предложить юзеру либо почистить диск, либо прервать выполнение.
Записан
fuCtor
Гость
« Ответ #3 : Апрель 07, 2009, 05:46 »

сигнал не может возвращать значение, об этом сказано там же, в Signals and slots. Это противоречит здравому смыслу: что возвратится, после того, как сработают подряд несколько слотов?
Согласно здравому смыслу да, но технически это возможно, правда только при прямом соединении.

Qt::BlockingQueuedConnection работает приблизительно так: объект, эмитирующий сигнал пробегается по списку слотов или сигналов, соединенных с данным, для каждого ждущего этого сигнала объекта, в очередь событий нитки, который этот объект принадлежит, добавляется событие QEvent::MetaCall, после чего выполнение потока, в котором эмитируется сигнал, приостанавливается до тех пор, пока не завершится обработка всех событий QEvent::MetaCall, инициированных данным сигналом.
Если объект, вызвавший сигнал и его получатель принадлежат одной нитке - будет дедлок => надо проверять принадлежность объектов к разным ниткам перед вызовом connect c данным параметром.
Хотя эта фича довольно удобна в некоторых случаях, юзать ее надо с большой осторожностью. Если можно обойтись без нее - лучше не юзать.
Из собственного опыта: я юзал этот коннект, когда в дополнительной счетной нитке, в которой не было событийного цикла,  возникала какая-нибудь критическая ситуация - например, заканчивалось место на диске - и надо было предложить юзеру либо почистить диск, либо прервать выполнение.
В принципе так и думал, осталось ток разобраться на практике.
Только второй вопрос так  и остался открытым: как вызвать метод из основного потока, если при этом он должен вернуть еще значение?
Записан
Sergeich
Гость
« Ответ #4 : Апрель 07, 2009, 12:41 »

Только второй вопрос так  и остался открытым: как вызвать метод из основного потока, если при этом он должен вернуть еще значение?
Никак. Не парься. Просто передавай в параметрах сигнала указатель на переменную и меняй значение переменной в слотах. Пример:
Код:
void WorkingThread::run()
{
  forever {
    bool ok = doSomethingUsefulOperation();
    if ( !ok ) {
      bool abort = false;
      emit abortRequested(&abort);
      if (abort)
        return;
    }
  }
}

void SomethingGuiClass::onAbortRequested( bool* abort )
{
   if ( QMessageBox::critical( this, tr("Error"), tr("Shit happened. Cancel job?") ) == QMessageBox::Ok )
     *abort = true;
   else
     *abort = false;
}
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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