У меня был похожий вопрос, и ответы здесь не дали мне необходимую информацию. Поэтому, несмотря на принятый ответ, я добавлю то, чему научился, чтобы помочь следующему парню.
1) Как уже упоминалось в некоторых других ответах, вы можете использовать using
для потоков, возвращаемых из HttpWebRequest / WebRequest. Это просто хорошее стандартное программирование на c #.
Но на самом деле это не касается вопроса ОП (или моего), который касался удаления самого объекта HttpWebRequest.
2) Несмотря на то, что функция для получения запроса HttpWebRequest называется «Create», не существует подходящего Destroy, Close, Dispose или любого другого механизма, доступного для освобождения ресурсов от созданного объекта.
Это в основном принятый в настоящее время ответ.
3) Но среди всех ответов здесь есть предположение, что (кроме потоков) не осталось ничего важного, что нужно закрыть. И это не совсем правильно.
Используя ProcMon , вы можете увидеть TCP Connect
, TCP Send
и TCP Receive
, которые возникают при вызове GetResponse()
. Это то, что я ожидал увидеть. Но когда TCP Disconnect
происходит? Я предполагал, что это произойдет либо после того, как вы закончите получать ответ, либо в худшем случае, когда объект получит GC. Но реальность интереснее.
Вместо этого TCP-соединение остается активным ровно 2 минуты после вызова. Моя первая мысль была о том, сколько времени понадобится GC, чтобы обойти это, но нет. Вы можете сидеть в цикле GC.Collect () в течение этих 2 минут, и он не отпускает, пока не истечут 2 минуты. Это сохраняет соединение открытым как на клиенте, так и на сервере, и вызывает (некоторый) дополнительный сетевой трафик в течение этих 2 минут, чтобы поддерживать соединение.
Другая интересная вещь заключается в том, что даже если вы вызываете «Создать», это не означает, что обязательно будет создано другое TCP-соединение. Например, рассмотрим это:
static void Doit(string domain)
{
HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(domain);
using (HttpWebResponse response = (HttpWebResponse)hr.GetResponse())
using (Stream receiveStream = response.GetResponseStream())
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
Console.WriteLine(readStream.ReadToEnd());
}
Теперь, если я позвоню с:
Doit("http://www.foo.bar");
Будет создано 1 TCP-соединение. Он будет активен в течение 2 минут (или до выхода из программы). Но что, если я сделаю это:
Doit("http://www.foo.bar");
Thread.Sleep(20000);
Doit("http://www.foo.bar");
Теперь он создаст 1 соединение для первого вызова, затем повторно использует это соединение для второго вызова. Это означает, что соединение TCP будет оставаться активным в течение 2:20 минут. Поэтому, хотя мы и называем «Создать», это не создание соединения с нуля.
В основном это хорошо. Создание соединения (особенно HTTPS-соединения) может быть дорогостоящим процессом. Система, которая автоматически избегает этого, является (вероятно) хорошей вещью. Таким образом, вы можете эффективно получить html для веб-страницы, а затем любые связанные файлы поддержки (css, img files и т. Д.) Без необходимости каждый раз проходить процесс подключения.
Но что, если сервер, к которому вы подключаетесь, поддерживает только ограниченное количество подключений? Оставить связанное соединение без уважительной причины может быть настоящей проблемой. Или, возможно, из соображений безопасности вы не можете оставлять соединения открытыми так долго? Или, может быть, вы просто анальный и хотите закрыть все, как только закончите.
В этих случаях вы можете поэкспериментировать с HttpWebRequest.KeepAlive
. Установка этого параметра на false
(по умолчанию true
) заставляет каждый из приведенных выше примеров использовать свое собственное соединение, отключая их, как только вы закончите. Таким образом, весь процесс подключения / отправки / получения / отключения может завершиться менее чем за секунду.
FYI:
- Хотя вы можете использовать WebRequest.InitializeLifetimeService для получения ILease, изменение значений аренды не влияет на время ожидания здесь.
- Вместо использования WebRequest вы можете использовать WebClient, который поддерживает Dispose. Однако лежащее в основе TCP-соединение все еще зависает в течение 2 минут даже после вызова Dispose.
В заключение. Сказать, что вам не нужно беспокоиться о закрытии HttpWebClient, может быть в целом верно, но есть некоторые последствия, о которых вы, возможно, захотите знать. Есть веские причины для такого поведения, но вы не можете решить, подходит ли это для вашего конкретного приложения, если вы не знаете, что это происходит.
FWIW