410 Stimmen

Müssen HttpClient und HttpClientHandler zwischen Anfragen entsorgt werden?

System.Net.Http.HttpClient und System.Net.Http.HttpClientHandler in .NET Framework 4.5 implementieren IDisposable (über System.Net.Http.HttpMessageInvoker).

Die Dokumentation zum using Statement sagt:

Im Allgemeinen sollten Sie, wenn Sie ein IDisposable-Objekt verwenden, es in einem using-Statement deklarieren und instanziieren.

Diese Antwort verwendet dieses Muster:

var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair("foo", "bar"),
        new KeyValuePair("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = client.PostAsync("/test", content).Result;
    result.EnsureSuccessStatusCode();
}

Aber die sichtbarsten Beispiele von Microsoft rufen Dispose() weder explizit noch implizit auf. Zum Beispiel:

In den Kommentaren der Ankündigung fragte jemand den Microsoft-Mitarbeiter:

Nach Überprüfung Ihrer Beispiele habe ich gesehen, dass Sie die Dispose-Aktion auf der HttpClient-Instanz nicht ausgeführt haben. Ich habe alle Instanzen von HttpClient mit dem using-Statement in meiner App verwendet und dachte, dass dies der richtige Weg ist, da HttpClient das IDisposable-Interface implementiert. Befinde ich mich auf dem richtigen Weg?

Seine Antwort war:

Im Allgemeinen ist das richtig, obwohl Sie bei "using" und async vorsichtig sein müssen, da sie in .NET 4 nicht wirklich zusammenpassen. In .NET 4.5 können Sie "await" innerhalb eines "using"-Statements verwenden.

Übrigens können Sie den gleichen HttpClient so oft wiederverwenden, wie Sie möchten, daher müssen Sie sie in der Regel nicht ständig erstellen/entsorgen.

Der zweite Absatz ist für diese Frage überflüssig, da es nicht darum geht, wie oft Sie eine HttpClient-Instanz verwenden können, sondern ob es notwendig ist, diese zu entsorgen, nachdem Sie sie nicht mehr benötigen.

(Update: In der Tat ist dieser zweite Absatz der Schlüssel zur Antwort, wie unten von @DPeden angegeben.)

Also meine Fragen sind:

  1. Ist es angesichts der aktuellen Implementierung (.NET Framework 4.5) erforderlich, Dispose() auf HttpClient- und HttpClientHandler-Instanzen aufzurufen? Klarstellung: Mit "erforderlich" meine ich, ob es negative Konsequenzen gibt, wenn Sie keine Entsorgung durchführen, wie beispielsweise Ressourcenlecks oder Risiken für Datenkorruption.

  2. Wenn es nicht erforderlich ist, wäre es trotzdem eine "gute Praxis", da sie IDisposable implementieren?

  3. Wenn es erforderlich (oder empfohlen) ist, implementiert der oben erwähnte Code dies sicher (für .NET Framework 4.5)?

  4. Wenn diese Klassen keine Dispose()-Aufrufe erfordern, warum wurden sie dann als IDisposable implementiert?

  5. Wenn sie erforderlich sind oder es eine empfohlene Praxis ist, sind die Microsoft-Beispiele irreführend oder unsicher?

0voto

Dave Black Punkte 6469

Nein, erstellen Sie nicht bei jeder Anfrage ein neues (auch wenn Sie über die alten verfügen). Sie werden den Server selbst (nicht nur die Anwendung) zum Absturz bringen, weil am Netzwerklevel des Betriebssystems der Porterschöpfung ausgeht!

Bitte lesen Sie meine Antwort auf eine sehr ähnliche Frage, die weiter unten gepostet wurde. Es sollte klar sein, dass Sie HttpClient-Instanzen als Singleton behandeln und über Anfragen hinweg wiederverwenden sollten.

Was ist der Overhead bei der Erstellung eines neuen HttpClient pro Aufruf in einem WebAPI-Client?

-2voto

yayadavid Punkte 434

Ich denke, man sollte das Singleton-Muster verwenden, um zu vermeiden, ständig Instanzen des HttpClient zu erstellen und zu schließen. Wenn Sie .Net 4.0 verwenden, könnten Sie einen Beispielcode wie unten verwenden. Weitere Informationen zum Singleton-Muster finden Sie hier.

class HttpClientSingletonWrapper : HttpClient
{
    private static readonly Lazy Lazy= new Lazy(()=>new HttpClientSingletonWrapper()); 

    public static HttpClientSingletonWrapper Instance {get { return Lazy.Value; }}

    private HttpClientSingletonWrapper()
    {
    }
}

Verwenden Sie den folgenden Code.

var client = HttpClientSingletonWrapper.Instance;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X