Подтвердить что ты не робот

Есть ли правильный способ утилизации httpwebrequest?

Я использую HttpWebRequest и удаляю поток ответов. Есть ли правильный способ утилизации HttpWebRequest, поскольку он не содержит метода close или dispose?

4b9b3361

Ответ 1

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

Ответ 2

У меня был аналогичный вопрос, и ответы здесь не дали мне необходимой информации. Поэтому, хотя есть приемлемый ответ, я собираюсь добавить то, что я научился, чтобы помочь следующему парню.

1) Как упоминают некоторые другие ответы, вы можете использовать using для потоков, возвращаемых из HttpWebRequest/WebRequest. Это просто хорошее стандартное программирование С#.

Но на самом деле это не касается вопроса OP (или моего), который касался утилизации самого объекта HttpWebRequest.

2) Несмотря на то, что функция для получения HttpWebRequest называется "Create", для освобождения ресурсов от созданного объекта не существует соответствующих Destroy, Close, Dispose или любого другого механизма.

Это в основном принятый в настоящее время ответ.

3). Но среди всех ответов здесь есть смысл, что (кроме потоков) нет ничего важного, что нужно было бы закрыть, что нужно закрыть. И это не совсем правильно.

Используя ProcMon, вы можете видеть TCP Connect, TCP Send и TCP Receive, которые возникают при вызове GetResponse(). Это то, что я ожидал увидеть. Но когда происходит TCP Disconnect? Мое предположение заключалось в том, что это произойдет либо после того, как вы закончите получать ответ, либо в худшем случае, когда объект получит GC'ed. Но реальность более интересна.

Вместо этого TCP-соединение остается активным ровно через 2 минуты после вызова. Моя первая мысль заключалась в том, что сколько времени понадобится GC, чтобы обойти это, но нет. Вы можете сидеть там в цикле GC.Collect() для этих 2 минут, и он не отпускает до тех пор, пока не начнется 2 минуты. Это держит соединение открытым как на клиенте, так и на сервере, и вызывает (некоторый) дополнительный сетевой трафик на эти 2 минуты, чтобы поддерживать соединение.

Еще одна интересная вещь: даже если вы вызываете "Create", это не означает, что при необходимости создается другое соединение 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 файлы и т.д.) Без необходимости проходить процесс подключения каждый раз.

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

В этих случаях вы можете поэкспериментировать с HttpWebRequest.KeepAlive. Установка этого параметра на false (по умолчанию - true) приводит к тому, что каждый из приведенных выше примеров использует свое собственное соединение, закрывая их, как только вы закончите. Таким образом, весь процесс Connect/Send/Receive/Disconnect завершится менее чем за секунду.

FYI:

  • Хотя вы можете использовать WebRequest.InitializeLifetimeService для получения ILease, изменение значений в аренде не влияет на таймауты здесь.
  • Вместо использования WebRequest вы можете использовать WebClient, который поддерживает Dispose. Однако основное TCP-соединение все еще висит в течение 2 минут даже после вызова Dispose.

В заключение: высказывание о том, что вам не нужно беспокоиться о закрытии HttpWebClient, может быть в целом верным, но есть последствия, о которых вы, возможно, захотите узнать. Для этого есть веские причины, но вы не можете решить, хорошо ли это для вашего конкретного приложения, если вы не знаете, что это происходит.

FWIW

Ответ 3

httpwebRequest не реализует IDisposable, так как он может создать Stream, который реализует IDisposable. Таким образом, вы не должны беспокоиться об утилизации.

Если вы беспокоитесь, вы можете использовать WebClient, который IDisposable:

using (WebClient c = new WebClient())
{
using (Stream stream = c.OpenRead(url))
{
//
}
}

Ответ 4

Вы можете использовать:

    var webRequest = WebRequest.Create(ActionUrl)
    using (var webResponse = webRequest.GetResponse())
    {}

для вашей реализации. Когда я использовал класс WebRequest для запуска нескольких запросов за очень короткий промежуток времени, обертывание GetResponse() в используемом блоке предотвращает зависание приложения.

Ответ 5

HttpWebRequest не реализует IDisposable, поэтому он не требует утилизации. просто установите объект httprequest равным null, как только вы закончите с ним.

Надеюсь, что это поможет