Как правильно избавиться от экземпляра WebResponse?

Обычно, каждый пишет код что-то вроде этого для загрузки некоторых данных с помощью WebRequest.

using(WebResponse resp = request.GetResponse())  // WebRequest request...
   using(Stream str = resp.GetResponseStream())  
      ; // do something with the stream str

Теперь, если WebException брошен, WebException имеет ссылку на объект WebResponse, который может или не может иметь, Располагают названный (в зависимости от того, где исключение произошло, или как класс ответа реализован) - я не знаю.

Мой вопрос состоит в том, как каждый, как предполагается, имеет дело с этим. Каждый, как предполагается, кодирует очень оборонительно и избавляется от ответа в объекте WebException (который был бы немного странным, поскольку WebException не является IDisposable). Или каждый, как предполагается, игнорирует это, потенциально получая доступ к склонному объекту или никогда не располагая объект IDisposable? Пример, данный в документации MSDN для WebException. Ответ является совершенно несоответствующим.

21
задан Marcus 11 December 2009 в 10:57
поделиться

4 ответа

Я быстро ознакомился с Reflector и теперь могу сказать:

  • WebResponse , будучи абстрактным классом, делегирует все свое поведение закрытия / удаления его производным классам. 1240] HttpWebResponse , являющийся производным классом, который вы почти наверняка используете здесь в своих методах закрытия / удаления, занимается только удалением фактического потока ответов. Остальную часть состояния класса можно оставить на милость GC.

Отсюда следует, что, вероятно, безопасно делать все, что угодно в отношении обработки исключений, при условии, что:

  • Когда вы читаете поток ответа из WebResponse в блоке try , заключите его в , используя блок .
  • Если вы читаете поток ответов из WebException в блоке catch , заключите его в , используя также блок .
  • Не нужно беспокоиться об удалении самого WebException .
16
ответ дан 29 November 2019 в 21:44
поделиться

Я почти уверен, что когда у вас есть оператор using, объект удаляется, независимо от того, как вы выходите из блока using (будь то исключение, возврат или просто выполнение функции).

Я подозреваю, что вы обнаружите, что объект внутри WebException уже удален, если вы позволите ему покинуть блок using.

Помните, что удаление объекта не обязательно предотвращает доступ к нему позже. Может быть непредсказуемо попытаться вызвать методы для него позже, что вызовет собственные исключения или очень странное поведение (и, следовательно, я бы не рекомендовал это). Но даже большая часть объекта по-прежнему остается для сборщика мусора, даже если вы его удалите, и, следовательно, все еще доступна. Целью удаления обычно является очистка дескрипторов ресурсов (как в этом случае активных TCP-соединений), которые по соображениям производительности вы не можете реально оставить лежать, пока их не найдет сборщик мусора. Я упоминаю об этом только для того, чтобы уточнить, что его удаление не является взаимоисключающим, а ссылка на него - исключением.

2
ответ дан 29 November 2019 в 21:44
поделиться

Очень интересный вопрос (хотя стоит отметить, что объект WebResponse будет удален при выходе из использования). Насколько я понимаю, на самом деле не имеет значения, что у вас есть ссылка на этот удаленный объект WebResponse, если вы не пытаетесь сделать с ним что-либо "работоспособное".

Вы можете вероятно по-прежнему имеет доступ к определенным свойствам экземпляра для ведения журнала (например, ResponseUri) без получения ObjectDisposedException , но общая ссылка, содержащаяся в исключении, отсутствует, поэтому вы можете продолжить использование экземпляра.

Мне было бы интересно узнать, что говорят другие.

0
ответ дан 29 November 2019 в 21:44
поделиться
using (var x = GetObject()) {
     statements;
}

(почти) эквивалентен

var x = GetObject();
try {
    statements;
}
finally {
     ((IDisposable)x).Dispose();
}

, поэтому ваш объект всегда будет удален.

Это означает, что в вашем случае

try {
    using (WebResponse resp = request.GetResponse()) {
        something;
    }
}
catch (WebException ex) {
    DoSomething(ex.Response);
}

ex.Response будет тем же объектом, что и ваш локальный resp, который удаляется, когда вы переходите к обработчику catch. Это означает, что DoSomething использует удаленный объект и, скорее всего, завершится ошибкой с исключением ObjectDisposedException.

3
ответ дан 29 November 2019 в 21:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: