Я использую HttpWebRequest
и удаляю поток ответов. Есть ли правильный способ утилизации HttpWebRequest
, так как он не содержит метод закрытия или удаления?Есть ли правильный способ утилизации httpwebrequest?
ответ
Если класс имеет особые требования по утилизации, было бы реализовано IDisposable. Поскольку он не реализует IDisposable, вы можете предположить, что вам ничего особенного не нужно делать.
HttpWebRequest не реализует IDisposable, поэтому он не требует утилизации. просто установите для объекта httprequest значение null, как только вы закончите с ним.
Надеется, что это помогает
Зачем устанавливать значение null? Просто позволить ему выйти из области действия достаточно для GC, чтобы забрать его ..... –
httpwebRequest не реализует IDisposable, так как он может создавать Stream, который реализует IDisposable. Таким образом, вы не должны беспокоиться об утилизации.
Если вы обеспокоены тем не менее, вы можете использовать WebClient, который IDisposable:
using (WebClient c = new WebClient())
{
using (Stream stream = c.OpenRead(url))
{
//
}
}
Вы можете использовать:
var webRequest = WebRequest.Create(ActionUrl)
using (var webResponse = webRequest.GetResponse())
{}
для вашей реализации. Когда я использовал класс WebRequest для запуска нескольких запросов за очень короткий промежуток времени, обертывание GetResponse() в блоке использования предотвращает зависание приложения.
У меня был аналогичный вопрос, и ответы здесь не дали мне необходимой информации. Поэтому, хотя есть приемлемый ответ, я собираюсь добавить то, что научился, чтобы помочь следующему парню.
1) Как упоминают другие ответы, вы можете использовать using
для потоков, возвращаемых из HttpWebRequest/WebRequest. Это просто хорошее стандартное программирование на C#.
Но на самом деле это не касается вопроса OP (или моего), касающегося утилизации объекта HttpWebRequest.
2) Несмотря на то, что функция для получения HttpWebRequest называется «Создать», не существует соответствующего метода Destroy, Close, Dispose или любого другого механизма для освобождения ресурсов от созданного объекта.
Это в основном принятый в настоящее время ответ.
3) Но среди всех ответов есть смысл, что (кроме потоков) нет ничего важного, что можно было бы висели вокруг этого . будет закрыт. И это не совсем правильно.
Используя ProcMon, вы можете увидеть TCP Connect
, TCP Send
и TCP Receive
, которые происходят при вызове GetResponse()
. Это то, что я ожидал увидеть. Но когда происходит TCP Disconnect
? Мое предположение заключалось в том, что это произойдет либо после того, как вы закончите получать ответ, либо в худшем случае, когда объект получит GC'ed. Но реальность более интересная.
Вместо этого соединение 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-файлы и т. Д.) Без необходимости проходить процесс подключения каждый раз.
Но что, если сервер, к которому вы подключаетесь, поддерживает только ограниченное количество соединений? Оставив соединение, связанное таким образом, без уважительной причины, может стать реальной проблемой. Или, возможно, из соображений безопасности вы не можете оставлять связи открытыми надолго? Или, может быть, вы просто анал и хотите закрыть это дело, как только закончите с ним.
Для этих случаев вы можете поэкспериментировать с HttpWebRequest.KeepAlive
. Установка этого параметра на false
(по умолчанию true
) приводит к тому, что каждый из приведенных выше примеров использует свое собственное соединение, закрывая их, как только вы закончите. Таким образом, весь процесс Connect/Send/Receive/Disconnect завершится менее чем за секунду.
FYI:
- В то время как вы можете использовать WebRequest.InitializeLifetimeService получить ILease, изменив значения на аренду не влияет на время ожидания здесь.
- Вместо использования WebRequest вы можете использовать WebClient, который поддерживает Dispose. Однако базовое TCP-соединение все еще зависает в течение 2 минут даже после вызова Dispose.
В заключение: Говорить, что вам не нужно беспокоиться о закрытии HttpWebClient, может быть, как правило, правдой, но есть последствия, о которых вы, возможно, захотите узнать. Для этого есть веские причины, но вы не можете решить, хорошо ли это для вашего конкретного приложения, если вы не знаете, что это происходит.
FWIW
- 1. Правильный способ утилизации BackGroundWorker
- 2. Правильный способ утилизации Quartz.NET?
- 3. Каков правильный способ утилизации объекта ObjectContext?
- 4. Каков правильный способ утилизации класса с таймером?
- 5. Каков правильный способ утилизации сложной структуры данных?
- 6. Правильный способ утилизации экранов в Libgdx
- 7. Каков правильный способ утилизации окна WPF?
- 8. Правильный способ утилизации одноразового в пределах наблюдаемого
- 9. Правильный способ утилизации объекта в C#?
- 10. Есть ли правильный способ бенчмаркинга?
- 11. Есть ли способ утилизации набора данных Crystal Reports?
- 12. Есть ли эффективный способ утилизации ломтиков избыточной мощности?
- 13. Есть преимущество потоков утилизации
- 14. Что такое правильный способ утилизации прокси-сервера WCF?
- 15. Правильный способ утилизации памяти отображаются файлы в C#
- 16. Правильный способ утилизации партию памяти потоков в C#
- 17. Есть ли «правильный» способ читать CSV файлы
- 18. Есть ли правильный способ компоновки машинок?
- 19. Есть ли «правильный» способ абстрагировать мой код?
- 20. Есть ли правильный способ компоновки моего CSS?
- 21. Ruby: Есть ли правильный способ отступов case?
- 22. Есть ли правильный способ повторного использования идентификаторов?
- 23. Есть ли «правильный» способ добавления/удаления PieChart?
- 24. Есть ли «правильный» способ использования php?
- 25. Каков правильный способ утилизации новой формы без немедленного закрытия?
- 26. Каков правильный способ утилизации объектов при сбое приложения для Android?
- 27. Каков правильный способ создания и утилизации системного таймера?
- 28. Есть ли способ принудительного конвейеризации в HttpWebRequest без установки ServicePointManager.DefaultConnectionLimit?
- 29. Есть ли способ захватить элемент по ID с помощью httpwebrequest?
- 30. Правильный способ запуска нескольких HttpWebRequest, которые могут занять много времени
Существуют сценарии, в которых он не сразу выходит из сферы действия - особенно когда вы создаете несколько веб-запросов в течение короткого периода времени , Если вам нужно избавиться от него, просто добавьте его в 'IDisposable', а затем вызовите метод Dispose()' на нем. – 2015-12-30 11:13:29
@mee это не имеет значения. 'HttpWebRequest' не реализует' IDisposable'. –