2009-04-04 16 views

Odpowiedz

39

Jeśli klasa miał specjalne wymagania utylizacji, byłoby wdrożyć IDisposable. Ponieważ nie implementuje IDisposable, możesz założyć, że nie ma nic szczególnego, co musisz zrobić.

+0

Istnieją scenariusze, w których nie wychodzi to natychmiast poza zakres zastosowania - szczególnie gdy tworzysz wiele żądań internetowych w krótkim okresie czasu . Jeśli musisz go wyrzucić, po prostu wyrzuć go do 'IDisposable', a następnie wywołaj metodę' Dispose() '. –

+0

@ patrz, to nie ma znaczenia. 'HttpWebRequest' nie implementuje' IDisposable'. –

-2

HttpWebRequest nie implementuje IDisposable, więc nie wymaga utylizacji. wystarczy ustawić obiekt httprequest na wartość null, gdy skończysz.

Nadzieja pomaga

+14

Dlaczego ustawić wartość NULL? Po prostu pozwolenie, aby wykraczało poza zakres, wystarczy, by GC je odebrał ... –

3

httpwebRequest nie implementuje IDisposable, ponieważ może utworzyć strumień, który implementuje IDisposable. W związku z tym nie powinieneś się martwić o jego usunięcie.

Jeśli martwisz się, choć może chcesz używać WebClient, który jest IDisposable:

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

Można użyć:

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

dla swojej realizacji. Kiedy użyłem klasy WebRequest do odpalenia wielu żądań w bardzo krótkim czasie, owijanie GetResponse() w bloku przy użyciu uniemożliwia zawieszanie się aplikacji.

14

Miałem podobne pytanie, a odpowiedzi tutaj nie dostarczyły mi potrzebnych informacji. Więc nawet jeśli istnieje akceptowana odpowiedź, dodam to, czego nauczyłem się, aby pomóc następnemu facetowi.

1) Jako że niektóre z innych odpowiedzi wspominają, można użyć using dla strumieni zwróconych przez HttpWebRequest/WebRequest. To jest po prostu dobre standardowe programowanie C#.

Ale tak naprawdę nie odnosi się do pytania OP (lub moje), które dotyczyło pozbywania się samego obiektu HttpWebRequest.

2) Pomimo faktu, że funkcja uzyskiwania HttpWebRequest ma nazwę "Utwórz", nie istnieje żaden zgodny mechanizm Destroy, Close, Dispose ani żaden inny mechanizm dostępny do uwolnienia zasobów z utworzonego obiektu.

Jest to zasadniczo obecnie akceptowana odpowiedź.

3) Ale jest tu implikacja pośród wszystkich odpowiedzi, które tutaj (poza strumieniami) nie pozostawiają nic ważnego, aby zostać zamkniętym. potrzebuje. I nie jest to całkowicie poprawne.

Korzystanie ProcMon można zobaczyć TCP Connect, TCP Send i TCP Receive które występują podczas rozmowy GetResponse(). Tego właśnie mogłem się spodziewać. Ale kiedy pojawia się TCP Disconnect? Zakładałem, że stanie się to albo po otrzymaniu odpowiedzi, albo, co najgorsze, gdy obiekt otrzyma GC. Ale rzeczywistość jest bardziej interesująca.

Zamiast tego połączenie TCP pozostaje aktywne przez dokładnie 2 minuty po zakończeniu połączenia. Moja pierwsza myśl była taka, jak długo zajmuje to GC, ale nie. Możesz tam siedzieć w pętli GC.Collect() przez te 2 minuty i nie puszcza, dopóki nie minie 2 minuty.Dzięki temu połączenie jest otwarte zarówno na kliencie, jak i na serwerze, i powoduje (trochę) dodatkowy ruch sieciowy przez te 2 minuty, aby utrzymać połączenie przy życiu.

Inną interesującą rzeczą jest to, że pomimo tego, że wywołujesz "Utwórz", nie oznacza to, że konieczne jest utworzenie innego połączenia TCP. Na przykład, rozważ to:

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()); 
} 

Teraz, jeśli zgłoszę to z:

Doit("http://www.foo.bar"); 

Stworzy 1 połączenie TCP. Pozostanie aktywny przez 2 minuty (lub do momentu wyjścia programu). Ale co, jeśli mogę to zrobić:

Doit("http://www.foo.bar"); 
Thread.Sleep(20000); 
Doit("http://www.foo.bar"); 

Teraz stworzy 1 połączenie do pierwszego połączenia, a następnie ponowneże przyłącze do drugiego naboru. Oznacza to, że połączenie TCP pozostanie aktywne przez łącznie 2:20 minut. Tak więc, mimo że nazywamy "Utwórz", nie tworzy ono połączenia od zera.

Przeważnie jest to dobre. Nawiązanie połączenia (zwłaszcza połączenie HTTPS) może być kosztownym procesem. System, który automatycznie tego unika, jest (prawdopodobnie) dobrą rzeczą. W ten sposób można efektywnie odzyskać html dla strony internetowej, a następnie dowolnego z powiązanych plików pomocy technicznej (pliki css, img itp.) Bez konieczności przechodzenia przez proces łączenia za każdym razem.

Ale co, jeśli serwer, z którym się łączysz, obsługuje tylko ograniczoną liczbę połączeń? Pozostawienie takiego powiązania bez żadnego uzasadnionego powodu może być poważnym problemem. A może ze względów bezpieczeństwa nie możesz pozostawiać otwartych połączeń przez tak długi czas? A może po prostu jesteś analna i chcesz ją zamknąć, gdy tylko skończysz.

W tych przypadkach można eksperymentować z HttpWebRequest.KeepAlive. Ustawienie tego na false (domyślnie true) powoduje, że każdy z powyższych przykładów używa każdego z nich, zamykając je zaraz po zakończeniu. Cały proces Connect/Send/Receive/Disconnect może zakończyć się w mniej niż sekundę.

FYI:

  • Chociaż można użyć WebRequest.InitializeLifetimeService uzyskać ILease, zmieniając wartości w leasingu nie wpływa na limity czasu tutaj.
  • Zamiast korzystać z WebRequest, możesz użyć WebClient, który obsługuje Dispose. Jednak podstawowe połączenie TCP nadal pozostaje zawieszone przez 2 minuty, nawet po wywołaniu Dispose.

Podsumowując: Mówienie, że nie musisz martwić się o wyłączenie HttpWebClient może być ogólnie prawdziwe, ale są pewne konsekwencje, o których możesz być świadomy. Istnieją dobre powody takiego zachowania, ale nie możesz zdecydować, czy jest to dobre dla twojej aplikacji, jeśli nie wiesz, że tak się dzieje.

FWIW

Powiązane problemy