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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Использование QNetworkAccessManager. Где удалять QNetworkReply ?  (Прочитано 11449 раз)
voronElf
Гость
« : Декабрь 15, 2009, 08:38 »

Всем привет.

При использовании QNetworkAccessManager при финише запроса мы получаем объект ответа QNetworkReply. Создает этот объект QNetworkAccessManager и выдает его адрес, а вот насчет удаления этого объекта документация говорит, что удалять нужно ручками самому в коде. Хочу обсудить вопрос: в каком месте кода его удалять (не в конкретной програме, а в принципе) ?

Пробовал удалять в слоте, обрабатывающем сигнал finished(...) от QNetworkAccessManager. Нормально отрабатывает, проблема только в одной ситуации: используем прокси (QNetworkProxy) и если уходил запрос с неправильным логином(паролем) пользователя прокси (код статуса 407, ошибка 105 QNetworkReply) то прога вылетает  по обращении  недоступной памяти.

Если не удалять совсем, почистит ли Qt память с этого объекта по завершению приложения ?

экспериментировал на Qt 4.5.2

PS: Я понимаю, что можно запонинать адреса объектов QNetworkReply и грохать потом в месте кода, где уже гарантированно соединения завершены. Но это уже от конкретного кода зависит, а хотелось бы какой-нибудь унифицированный вариант придумать.
Записан
Dendy
Гость
« Ответ #1 : Декабрь 16, 2009, 23:08 »

В документации написано, что у QNetworkReply родителем ставится автоматически экземпляр QNetworkAccessManager, значит, что при удалении последнего удалятся и все запросы. Ещё посмотрите в сторону QObject::deleteLater(). Вообще удалять обьекты прямо в слотах опасно, так как обьект, испустивший сигнал, может на следующей строчке обратиться к этому удалённому экземпляру. Нужно смотреть каждый случай в отдельности.
Записан
voronElf
Гость
« Ответ #2 : Декабрь 17, 2009, 11:27 »

Ну вот видимо при ситуации  с прокси испустивший сигнал объект и обращается к уже удаленному. Покопаю в сторону QObject::deleteLater().
Записан
Dendy
Гость
« Ответ #3 : Декабрь 17, 2009, 11:36 »

Рекомендую делать: reply->abort(); reply->deleteLater(). Первое по идее заблокирует дальнейшее использование, чтобы на следующей строчке испускающий сигнал код мог проверить его состояние. Второе - прибьёт reply на следующей итерации главного цикла. Вообще в коде Qt встречается подобное:

Код
C++ (Qt)
QPointer self( this );
emit something();
if ( !self )
   return;

Но каждый случай должен быть документирован отдельно, что можно, а что нельзя удалять в слотах.
Записан
voronElf
Гость
« Ответ #4 : Декабрь 18, 2009, 10:48 »

Потестил (на ситуации с проксей) , достаточно одного reply->deleteLater(), вылетаний памяти уже нет (все таки очищается очередь событий к удаляемому объекту). Но надежнее конечно сначала делать явный reply->abort(). Я ж не абсолютно все ситуации протестил )))

Удалять в слотах конечно способ опасный (документация еще пишет о проблемах QObject::deleteLater() с новыми циклами событий). Но думаю для схемы работы QNetworkReply способ вполне применим. Буду использовать abort() и deleteLater().

P.S. Спасибо за комментарии
Записан
jjoss
Гость
« Ответ #5 : Декабрь 20, 2009, 19:13 »

Столкнулся с подобной проблемой.
Делаю так.

Код:
class ODSSCon : public QObject
{
Q_OBJECT
.............
private:
  QNetworkAccessManager manager;
  QNetworkRequest request;
  QNetworkReply *currentReply;
..............
public slots:
  void readyReadReply();
  void finishedReadReply();
  void replyError(QNetworkReply::NetworkError error);
..............
};

Затем:
Код:
....
currentReply = manager.get(request);
  connect(currentReply, SIGNAL(readyRead()), SLOT(readyReadReply()));
  connect(currentReply, SIGNAL(finished()), SLOT(finishedReadReply()));
  connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)),
          SLOT(replyError(QNetworkReply::NetworkError)));
....

И в слоте finishedReadReply() делаю currentReply->deleteLater(); Так же реализован пример QT $QT_DIR\examples\network\downloadmanager\.

Подряд делаю 2 запроса. В итоге, получаю данные только второго. Куда смотреть?
Записан
Dendy
Гость
« Ответ #6 : Декабрь 21, 2009, 03:10 »

Каждый запрос должен ложиться в отдельную переменную.
Записан
kataklysm
Гость
« Ответ #7 : Ноябрь 10, 2010, 15:05 »

Каждый запрос должен ложиться в отдельную переменную.
Столкнулся с такой же проблемой. Не подскажите как можно реализовать такое, при этом их n-количество. Спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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