crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в Http и потоки
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
BRE Дата 8.10.2009, 9:12
 
Цитата(rnd @ 8.10.2009, 9:54) *
Мне сложно представить многопоточное приложение, использующие очереди, в котором несанкционированная прокачка сообщений не будет проблемой. На эти грабли наступали уже не раз.
Приложение, над которым сейчас работаем активно использует пул потоков, пересылку сообщений между ними и минимум синхронизаций. Использование прокачки сообщений в коде - запрещено.

Такие ситуации возникают тогда, когда нитка запущена и в пустую крутит цикл обработки сообщений, ожидая прихода внешнего события. После чего в своем контексте выполняет необходимый код. К тому же у вас в контексте этой нити можно выполнять разный код (в зависимости от слота).
Вопрос: для чего эта нить висит и ждет этого события? Наверное лучше в нужный момент запустить нить, которая выполнит необходимое действие и завершиться.
А если нужны сложности, конечно можно ограничивать себя по "самые помидоры" и держать активную нить, которая будут пытаться в своем контексте выполнять множество разных действия. ;) :)

Цитата(rnd @ 8.10.2009, 9:54) *
Я не говорю, что это должна быть запрещенная практика, просто многие люди не задумываются, что реально происходит при таком подходе. И каждое использование прокачки сообщений должно быть обдумано несколько раз, со всеми возможными последствиями.

+мульон
rnd Дата 8.10.2009, 8:54
  Надуманный?:)
Это крайне упрощенный пример.

Мне сложно представить многопоточное приложение, использующие очереди, в котором несанкционированная прокачка сообщений не будет проблемой. На эти грабли наступали уже не раз.
Приложение, над которым сейчас работаем активно использует пул потоков, пересылку сообщений между ними и минимум синхронизаций. Использование прокачки сообщений в коде - запрещено.
Кстати модальные диалоги - тоже не айс, именно по этой причине.

Я не говорю, что это должна быть запрещенная практика, просто многие люди не задумываются, что реально происходит при таком подходе. И каждое использование прокачки сообщений должно быть обдумано несколько раз, со всеми возможными последствиями.
BRE Дата 7.10.2009, 22:09
  Тебе не кажется, что это немного надуманный пример.
Я привел тебе код, который будет работать в потоке синхронно.
Если существует возможность такой ситуации, о которой пишешь ты, то такие случаи нужно учитывать отдельно (например использовать Qt::BlockingQueuedConnection), а лучше так никогда не делать.
А прокрутка очереди сообщений, это вовсе не опасная практика. Она повсеместно используется в Qt: от оживления длительных операций и до модальных диалогов. Главное думать, что делаешь.
rnd Дата 7.10.2009, 21:33
  Давай отвлечемся от QNetworkAccessNanager - он тут совершенно не при чем сейчас

Смотри, есть два потока, в первом крутится obj1, во втором obj2:

Thr1 | Thr2
------ ------
Obj1 | Obj2


Первый поток эмитит два сигнала sig1, sig2 объекту, который находится во втором потоке.
Obj1 ->sig1->Obj2
Obj1 ->sig2->Obj2

Соответствующие слоты(slot1, slot2) не вызываются напрямую, а в очередь Thr2 кладутся сообщения для вызова этих слотов.


Дальше, Thr2 извлекает очередное сообщение, видит что это вызов слота slot1 - и вызывает его. Объект Obj2 переходит в несогласованное состояние. Внутри слота slot1 мы начинаем прокачивать сообщения (loop.exec()), Thr2 извлекает следующие сообщение из очереди - видит что это вызов слота slot2 и дергает его - опа приехали, еще не выйдя из slot1 уже запустили slot2!
Callstack:
----------
slot2()
.....
slot1()
....
------------

Естественно, вместо вызова слотов могут быть любые обработчики.

Для того чтобы решить эту проблему - и создается дополнительный поток - Thr3. В него помещается объект и сообщения этот объект получает в нем. А вызывающие поток ждет окончания Thr3 НЕ прокачивая при этом свои сообщения.
BRE Дата 7.10.2009, 13:51
 
Цитата(rnd @ 7.10.2009, 14:30) *
Ну смотри, допустим в очереди лежит два сообщения - на вызов Class1::slot1 и Class1::slot2. Вызывается slot1() - объект переходит в несогласованное состояние. Начинаем прокачку сообщений - сразу вызыватеся slot2, т.е. колл-стек такой:

Мне лучше на примере кода показать.
Откуда взялись сообщения, кто их туда положил? Вообще, как ты себе все это представляешь.

Продублирую сообщение. Вот примерный код двух разных потоков. Что бы разговор был более предметным.

Ты считаешь, что при таком коде ненужные слоты вызываться не будут:
void Thread::run()
{
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), SLOT( replyFinished(QNetworkReply*) ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );

    exec();
}


а при таком будут?
void Thread::run()
{
    QEventLoop loop;
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), &loop, SLOT( quit() ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );
    loop.exec();
    // обработка ответа...
}


Где и какие ненужные сообщения/сигналы/слоты будут вызываться?
rnd Дата 7.10.2009, 13:30
  Ну смотри, допустим в очереди лежит два сообщения - на вызов Class1::slot1 и Class1::slot2. Вызывается slot1() - объект переходит в несогласованное состояние. Начинаем прокачку сообщений - сразу вызыватеся slot2, т.е. колл-стек такой:

----------------
slot2()
...
slot1()
...
-----------------

Поскольку объект в несогласованном состоянии (выполнение slot1 еще не закончилось) - ахтунг!

Цитата(BRE @ 7.10.2009, 14:22) *
Зря, что не стал.

За это не платят:)
BRE Дата 7.10.2009, 13:29
 
Цитата(rnd @ 7.10.2009, 14:18) *
В смысле какие слоты? Обычные слоты, естественно emit которым был сделан из другого потока. Да и вообще, начнут вызываться все обработки - неважно слот, метаколл или эвент. Если пример еще нужен - могу привести.

Конечно нужны примеры.
Какие ненужные слоты начнут выполняться? По-подробней.

Цитата(rnd @ 7.10.2009, 14:18) *
выяснять не стал

Зря, что не стал.

Ты считаешь, что при таком коде ненужные слоты вызываться не будут:
void Thread::run()
{
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), SLOT( replyFinished(QNetworkReply*) ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );

    exec();
}


а при таком будут?
void Thread::run()
{
    QEventLoop loop;
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), &loop, SLOT( quit() ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );
    loop.exec();
}

rnd Дата 7.10.2009, 13:18
 
Цитата(BRE @ 7.10.2009, 14:03) *
Как ты себе это представляешь? Какие не нужные слоты начнут отрабатывать посреди работы этой функции. Можно по-подробней. Желательно с примерами.


В смысле какие слоты? Обычные слоты, естественно emit которым был сделан из другого потока. Да и вообще, начнут вызываться все обработки - неважно слот, метаколл или эвент. Если пример еще нужен - могу привести.

Цитата(BRE @ 7.10.2009, 14:03) *
Кстати, не имеет значения что использовать QHttp или QNetworkAccessManager.


Как оказалось - имеет, QNetworkAccessManager не виснет в WaitForMultipleObject, почему различия - выяснять не стал
BRE Дата 7.10.2009, 13:03
 
Цитата(rnd @ 7.10.2009, 13:57) *
BRE, то, что вы предлагаете - очень опасная практика. Начнут прокачиваться сообщения, т.е. вызываться слоты\обработчики, которые в данный момент времени (посреди работы функции) вызываться совершенно не должны.

Как ты себе это представляешь? Какие не нужные слоты начнут отрабатывать посреди работы этой функции. Можно по-подробней. Желательно с примерами.
Если этот код будет выполняться в отдельном потоке, то и очередь сообщений будет использоваться этого потока.
Кстати, не имеет значения что использовать QHttp или QNetworkAccessManager.
rnd Дата 7.10.2009, 12:57
  BRE, то, что вы предлагаете - очень опасная практика. Начнут прокачиваться сообщения, т.е. вызываться слоты\обработчики, которые в данный момент времени (посреди работы функции) вызываться совершенно не должны.

Именно поэтому и создается отдельный поток, в который засовывается(moveToThread) объект QNetworkAccessManager там для него и идет прокачка сообщений, а вызывающий поток ждет.

Вчерашняя проблема решилась заменой QHttp на QNetworkAccessManager:)
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 18.4.2024, 9:53