Pull to refresh

Comments 25

из документации советуют использовать один QNetworkAccessManager для всего приложения, как вариант вынести твой RequestSender в отдельный поток, а тайм ауты сделать частью
рубанули эликтричество =( у нас тут с этим плохо
Не соглашусь с использованием одного QNetworkAccessManager-а на всё приложение. Бывают случаи, когда нужно отправлять запросы через прокси, причём прокси не один, а несколько. Тогда я создаю несколько RequestSender-ов и отправляю запросы с использованием прокси в разных потоках.
Ну раз зашла речь то неплохо бы еще тебе проверять редиректы вроде такого
if (statusCode >= 300 && statusCode < 400) {
        return kRedirect;
}
Рассмотри возможность вынести RequestSender в отдельный поток сделав менеджер его частью. Там же хранить сет реквестов и их id. Тайм ауты можно контролировать через QSignalMapper получаю в итоге id request который отвалился
Если не ошибаюсь, функции асинхронные, зачем в поток-то?
Асинхронные. Одна из задач класса RequestSender — скрыть эту асинхронность.
Работа с REST API в Qt, больная тема, конечно, приходится писать приличных размеров велосипеды — и все осложняется недостатком информации как правильно реализовывать нюансы этой работы.

Как уже писали выше, решение использовать QEventLoop выглядит странным, вследствии чего выполняется не менее странная проверка успешности выполнения в том же методе, без использования механизма сигналов/слотов. RequestError имеет всего два состояния, хватило бы возвращать bool. Хотя по сути ошибок может быть значительно больше, что в этой реализации не отлавливается в соответствующем слоте. Исключение как стандартный метод возврата результата в Qt — жуткий моветон, заставлять текущий (возможно главный) поток спать в бесконечном цикле, опять же без сигналов/слотов — быдлокод, и т.д.

Не хотелось бы отбить желание выкладывать код, но если честно, то Request выглядит не сильно полезнее стандартной связки QUrl + QUrlQuery, Network же с одной стороны примитивный, с другой стороны написан криво :/
RequestError имеет всего два состояния, хватило бы возвращать bool. Хотя по сути ошибок может быть значительно больше

Да, именно потому, что ошибок может быть больше, не возвращается bool. Для моих целей мне, пока что, хватило этих двух состояний. Однако, было бы неплохо обрабатывать и другие случаи.
заставлять текущий (возможно главный) поток спать в бесконечном цикле, опять же без сигналов/слотов — быдлокод, и т.д.

А какую реализацию предложите для «избавления» от асинхронности QNetworkAccessManager? Не сказал бы «спал», скорее ожидание события. Если бы вы использовали другую библиотеку, которая работает не асинхронно, то у вас и там главный поток «спал», пока не придёт ответ. Я пока ничего лучшего кроме как связки с QEventLoop-ом не придумал.
Я пока ничего лучшего кроме как связки с QEventLoop-ом не придумал.
Стандартный случай для этого — очередь. В связке с со слотом, подписанным на finished(), конечно.
Upd:
Не сказал бы «спал», скорее ожидание события
И в это время он ничего не делает, верно? Спит в ожидании события, хорошо.
Если бы вы использовали другую библиотеку, которая работает не асинхронно, то у вас и там главный поток «спал», пока не придёт ответ.
Давайте еще микроконтроллеры вспомним, ага. У нас ведь главный поток отвечает за отрисовку интерфейса пользователя, и если он спит пока идет запрос (максимум 2*n секунд) — UI не отвечает на внешние раздражители.
Давайте еще микроконтроллеры вспомним, ага. У нас ведь главный поток отвечает за отрисовку интерфейса пользователя, и если он спит пока идет запрос (максимум 2*n секунд) — UI не отвечает на внешние раздражители.

Никаких фризов не происходит, интерфейс отрисовывается и реагирует на все события. Благодаря использованию QEventLoop::exec.
Если мы вызываем sendWhileSuccess и у нас все maxCount раз неудачно проходит запрос — то никаких фризов нет?
Что по-вашему фризы? Вот мы без перерыва кликаем, например, в чекбокс во время этого действа, и он мгновенно меняет свое состояние сколько бы мы не кликали?
loop.exec(); Фризит в том то и дело. Он не отпустит пока не придет сигнал finished, это и есть способ сделать из асинхронной функции синхронную. А тем более вы вообще sleep потом вызываете.
Вы же сами писали «Одна из задач класса RequestSender — скрыть эту асинхронность.».
Чтобы гуи рисовались надо в циклах вызывать QApplication::processEvents(), можно там к примеру таймер завести 30 раз в секунду вызывать QApplication::processEvents().

А если честно, то я вообще не пойму поставленной задачи. QNetworkAccessManager простой как кирпич. Зачем все это объясните пожалуйста? Создал приемник сигналов от reply и радуешься. Хоть прогрессбары делай, хоть что… Отправил запрос и забыл. Ждешь в слоте.
Какой sleep? Никакой sleep не вызывается. Я ещё раз говорю, что не фризится гуи. Соберите и проверьте сами.

QNetworkAccessManager простой как кирпич.

Но не всегда удобный. Чтобы отправить один запрос, создавать QNetworkAccessManager, соединять сигналы со слотами (ещё и слот создавать), потом заботится об удалении QNetworkReply… Слишком много «движений» для отправки одного запроса. А мой класс всё это скрывает.
Какой sleep? Никакой sleep не вызывается.
QThread::currentThread()->msleep(2000);
loop.exec(); Фризит в том то и дело...
Тут вы не правы, что не удивительно — с таким извращением встречаешься не каждый день. Очередь событий общая для потока, и если запущен хоть один QEventLoop, события обрабатываться будут нормально, потому в данном случае вызывать QApplication::processEvents() смысла нет. Я так понимаю когда мы делаем что-нибудь вроде QDialog::exec() — применяется похожий подход.
Почему извращение? Обработка событий, на то и обработка событий, чтобы события обрабатывались… Если вы сразу этого не поняли, значит не до конца понимаете как устроены события в Qt.

З.Ы. Насчёт msleep — я думал мы с товарищем midday рассматривали метод sendRequest. Если говорить о sendWhileSuccess — соглашусь, не совсем корректно его (msleep) тут использовать. Лучше заменить его на… QEventLoop.
Обработка событий, на то и обработка событий, чтобы события обрабатывались…
Спасибо за информацию.

Если вы сразу этого не поняли, значит не до конца понимаете как устроены события в Qt.
Тут вы правы, мне еще учиться и учиться. Только вот согласно документации, работа с QNetworkAccessManager должна быть построена с использованием механизма слотов и сигналов, как и вся остальная система событий в Qt.

Насчёт msleep — я думал мы с товарищем midday рассматривали метод sendRequest.
Заблудились в двух собственных методах? Печально.

Лучше заменить его на… QEventLoop.
Хорошо хоть вы до конца понимаете как устроены события в Qt, и просветили нас новеллой с тремя вложенными QEventLoop в программе с тремя классами.
Заблудились в двух собственных методах? Печально.

Сарказмщик. Сформулирую инчае — я думал, речь идёт об одном методе, а не о двух.

с тремя вложенными QEventLoop в программе с тремя классами.

По вашей логике, вызов QDialog::exec — не самая лучшая идея, так как фактически получается цикл обработки в цикле обработке, то есть два цикла вложенные друг в друга.
Ага. Да туплю. QEventLoop не фризит. Но слип нужно заменить. Хотя все это противоречит всей идеалогии.
Sign up to leave a comment.

Articles