Müssen HttpClient und HttpClientHandler entsorgt werden?
System.Net.Http.HttpClient und System.Net.Http.HttpClientHandler.NET Framework 4.5 implementieren Sie IDisposable (über System.Net.Http.HttpMessageInvoker).
Den using
Anweisung-Dokumentation sagt:
Regel, wenn Sie ein IDisposable-Objekt, sollten Sie erklären und
instanziieren Sie in einer using-Anweisung.
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<string, string>("foo", "bar"),
new KeyValuePair<string, string>("baz", "bazinga"),
});
cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
var result = client.PostAsync("/test", content).Result;
result.EnsureSuccessStatusCode();
}
Aber die offensichtlichsten Beispiele von Microsoft nicht aufrufen Dispose()
entweder explizit oder implizit. Zum Beispiel:
- Die ursprünglichen blog-Artikel der Bekanntgabe der Release von HttpClient.
- Die tatsächliche MSDN-Dokumentation für HttpClient.
- BingTranslateSample
- GoogleMapsSample
- WorldBankSample
In der Ankündigung's Kommentaren hat jemand gefragt, die Microsoft-Mitarbeiter:
Nach Prüfung der Proben, sah ich, dass Sie nicht führen Sie die Entsorgung
Aktion auf HttpClient-Instanz. Ich habe alle Instanzen von HttpClient
mit der using-Anweisung auf mein app, und ich dachte, dass dies der richtige Weg ist
da HttpClient implementiert die IDisposable-Schnittstelle. Ich bin auf der
richtigen Weg?
Seine Antwort war:
In der Regel, dass richtig ist, obwohl Sie müssen vorsichtig sein mit
"mit" und "async", da Sie nicht wirklich in .Net 4, In .Net 4.5
verwenden können, "erwarten" innen "using" - Anweisung.Btw, können Sie die Wiederverwendung der gleichen HttpClient wie viele Male sind [wie] Sie wie so
in der Regel werden Sie nicht schaffen/entsorgen Sie die ganze Zeit.
Dem zweiten Absatz ist überflüssig, auf diese Frage, die ist nicht besorgt darüber, wie viele Male Sie können ein HttpClient-Instanz, sondern um wenn es notwendig ist, entsorgen Sie es nach Sie es nicht mehr benötigen.
(Update: in der Tat, dass der zweite Absatz ist der Schlüssel zur Antwort, wie weiter unten von @DPeden.)
Also meine Fragen sind:
- Ist es notwendig, angesichts der aktuellen Implementierung (.NET Framework 4.5), zum Aufruf von Dispose() HttpClient und HttpClientHandler Instanzen? Klarstellung: mit "notwendig" meine ich, ob es irgendwelche negativen Konsequenzen, wenn man nicht entsorgen, wie die Ressource Leckage oder Beschädigung von Daten Risiken.
- Wenn es nicht notwendig ist, wäre es ein "good practice" wie auch immer, da Sie IDisposable implementieren?
- Wenn es erforderlich (oder empfohlen), ist dieser code oben genannten Umsetzung ist es sicher (für .NET Framework 4.5)?
- Wenn diese Klassen nicht erforderlich, der Aufruf von Dispose(), warum wurden Sie implementiert IDisposable?
- Wenn Sie erforderlich ist, oder wenn es empfohlen wird, sind die Microsoft-Beispiele irreführender oder unsicher?
InformationsquelleAutor der Frage Fernando Correia | 2013-03-29
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der Allgemeine Konsens ist, dass Sie nicht (sollte nicht) entsorgen müssen HttpClient.
Viele Menschen, die sehr eng eingebunden in die Art, wie es funktioniert angegeben haben.
Sehen Darrel Miller ' s blog-post und im Zusammenhang DAMIT posten: HttpClient-crawling-Ergebnisse in Speicherverlust für Referenz.
Ich würde auch empfehlen, dass Sie Lesen die HttpClient-Kapitel von Gestaltung Optimierbare Web-APIs mit ASP.NET Kontext auf, was Los ist unter der Haube, vor allem das "Lifecycle" - Abschnitt hier zitiert:
Oder sogar öffnen DotPeek.
InformationsquelleAutor der Antwort David Peden
Aktuelle Antworten sind etwas verwirrend und irreführend, und Sie fehlen einige wichtige DNS-Auswirkungen. Ich werde versuchen, zusammenzufassen, wo die Dinge stehen klar.
IDisposable
Objekte idealerweise sollten entsorgt werden, wenn Sie fertig sind mit Ihnenvor allem diejenigen, die eigenen Namens/shared-OS-Ressourcen.HttpClient
ist keine Ausnahme, da Darrel Miller Punkte heraus, es weist Stornierung Token und request/response-Körper können werden nicht verwalteten streams.Connection:close
- header nach dem DNS Veränderungen stattfinden. Eine weitere Möglichkeit ist das recycling derHttpClient
auf der client-Seite, entweder in regelmäßigen Abständen oder über einen Mechanismus, der erfährt mehr über die DNS zu ändern. Sehen https://github.com/dotnet/corefx/issues/11224 für mehr Informationen (ich schlage vor, Lesen Sie es sorgfältig durch, bevor Sie blind mit dem code vorgeschlagen, in dem verlinkten blog-post).InformationsquelleAutor der Antwort Ohad Schneider
In meinem Verständnis, Berufung
Dispose()
ist nur notwendig, wenn es das sperren von Ressourcen, die Sie später brauchen (wie eine Verbindung). Es ist immer empfohlenum freie Ressourcen, Sie sind nicht mehr mit, selbst wenn Sie nicht Sie wieder brauchst, einfach, weil Sie sollte nicht in der Regel sein festhalten an Ressourcen, die Sie nicht verwenden (Wortspiel beabsichtigt).Dem Microsoft-Beispiel ist nicht falsch, unbedingt. Alle verwendeten Ressourcen werden freigegeben, wenn die Anwendung beendet wird. Und in dem Fall, das Beispiel, das passiert fast sofort nach der
HttpClient
getan wird, verwendet wird. In wie Fällen explizit aufrufenDispose()
ist etwas überflüssig.Aber, in der Regel, wenn eine Klasse implementiert
IDisposable
das Verständnis ist, dass Sie solltenDispose()
seiner Instanzen, sobald Sie voll sind, die bereit und in der Lage. Ich würde behaupten dies ist insbesondere wahr in Fällen wieHttpClient
wobei es nicht explizit dokumentiert ist, ob Ressourcen oder verbindungen statt auf/öffnen. In dem Fall, in dem die Verbindung wiederverwendet wird wieder [bald], Sie werden wollen, zu verzichtenDipose()
ing -- Sie sind nicht "völlig fertig" in diesem Fall.Siehe auch:
IDisposable.Dispose-Methode und Wenn beim Aufruf von Dispose
InformationsquelleAutor der Antwort svidgen
Dispose () - Aufrufe im code unten, das schließt die verbindungen geöffnet, durch die HttpClient-Instanz. Der code wurde von der Dekompilierung mit dotPeek.
HttpClientHandler.cs - Entsorgen
Wenn Sie nicht rufen Sie dispose dann ServicePointManager.MaxServicePointIdleTime, die läuft über eine Zeitschaltuhr wird in der Nähe der http-verbindungen. Der Standardwert ist 100 Sekunden.
ServicePointManager.cs
Wenn Sie haben nicht die idle-time auf unendlich, dann scheint es sicher nicht zu nennen, entsorgen und lassen Sie die Verbindung im Leerlauf-timer kick-in, und schließen Sie die verbindungen für Sie, obwohl es besser wäre für Sie, rufen Sie dispose in einer using-Anweisung, wenn Sie wissen, dass Sie fertig sind mit einem HttpClient-Instanz und die Ressourcen schneller.
InformationsquelleAutor der Antwort Timothy Gonzalez
In meinem Fall, ich war die Schaffung eines HttpClient innerhalb einer Methode, die tatsächlich den service-Aufruf. So etwas wie:
In einer Azure worker-Rolle, nach wiederholter Aufruf dieser Methode (ohne Entsorgung der HttpClient), wäre es schließlich nicht mit
SocketException
(Verbindung fehlgeschlagen).Machte ich den HttpClient eine Instanz-variable (Entsorgung es auch in der Klasse) und das Problem ging Weg. Also ich würde sagen, ja, entsorgen Sie die HttpClient, vorausgesetzt, dass der safe (Sie haben keine ausstehenden asynchronen Aufrufe) zu tun.
InformationsquelleAutor der Antwort David Faivre
In der typischen Verwendung (Reaktionen<2GB) ist es nicht notwendig, Entsorgen Sie die HttpResponseMessages.
Die Rückgabetypen der HttpClient-Methoden, sollten Entsorgt werden, wenn Ihre Stream-Inhalt wird nicht vollständig Gelesen. Ansonsten gibt es keine Möglichkeit für die CLR zu wissen das die Streams geschlossen werden kann, bis Sie von der garbage Collection eingesammelt.
Wenn Sie die HttpCompletionOption zu ResponseHeadersRead oder die Antwort größer als 2 GB ist, sollten Sie Aufräumen. Dies kann durch den Aufruf von Dispose auf der HttpResponseMessage oder durch den Aufruf von Dispose/Schließen auf den Strom erhalten Sie aus der HttpResonseMessage Inhalte oder durch das Lesen der Inhalte vollständig.
Ob Sie rufen Sie Dispose auf der HttpClient hängt davon ab, ob Sie Abbrechen möchten ausstehende Anforderungen oder nicht.
InformationsquelleAutor der Antwort Tom Deseyn
Wenn Sie möchten, entsorgen Sie HttpClient, können Sie, wenn Sie es als eine Ressource pool. Und am Ende der Anwendung, Sie verfügen über Ihren resource pool.
Code:
var handler = HttpClientHander.GetHttpClientHandle(new Uri("Basis-url")).
Oder wenn das Programm bereinigt das Objekt durch seine Destruktor.
InformationsquelleAutor der Antwort TamusJRoyce
Verwendung von dependency injection, die in Ihrem Konstruktor macht die Verwaltung der Lebensdauer der
HttpClient
einfacher - wobei die Lebensdauer managemant außerhalb des Codes, die es braucht und macht es leicht änderbar zu einem späteren Zeitpunkt.Meine aktuelle Präferenz ist, erstellen Sie eine separate http-client-Klasse, die erbt von
HttpClient
einmal pro Ziel-endpoint-domain und dann machen es zu einem singleton-Verwendung von dependency injection.public class ExampleHttpClient : HttpClient { ... }
Dann nehme ich einen Konstruktor Abhängigkeit von der benutzerdefinierten http-client in der service-Klassen, in denen ich den Zugriff auf die API. Dies löst die Lebensdauer problem und hat Vorteile, wenn es um Verbindungs-pooling.
Sehen Sie ein Beispiel in Bezug Antwort auf https://stackoverflow.com/a/50238944/3140853
InformationsquelleAutor der Antwort alastairtree
Kurze Antwort: Nein, die Aussage in der derzeit akzeptierte Antwort ist NICHT korrekt: "Der Allgemeine Konsens ist, dass Sie nicht (sollte nicht) entsorgen müssen HttpClient".
Lange Antwort: die BEIDEN folgenden Aussagen sind wahr und achieveable zur gleichen Zeit:
IDisposable
Objekt soll/empfohlen entsorgt werden.Ist und Sie NICHT NOTWENDIGERWEISE miteinander in KONFLIKT geraten. Es ist nur eine Frage, wie organisieren Sie Ihren code wiederverwenden einer
HttpClient
noch UND entsorgen Sie es ordnungsgemäß.Einen noch mehr beantworten zitiert aus meinem eine andere Antwort:
Es ist kein Zufall, Leute zu sehen,
in einige blog-Beiträge Schuld, wie
HttpClient
'sIDisposable
- Schnittstellemacht Sie neigen dazu, verwenden Sie die
using (var client = new HttpClient()) {...}
Musterund führen dann zu erschöpft socket-handler problem.
Ich glaube, dass kommt auf eine unausgesprochene (mis?)Konzeption:
"ein IDisposable-Objekt ist voraussichtlich von kurzer Dauer sein".
JEDOCH, während es sieht aus wie eine kurzlebige Sache, wenn wir code schreiben, der in diesem Stil:
den offizielle Dokumentation über die IDisposable -
nie erwähnt
IDisposable
Objekte müssen von kurzer Dauer sein.Per definition IDisposable ist lediglich ein Mechanismus, um zu ermöglichen, die Sie zur Freigabe von nicht verwalteten Ressourcen.
Nichts mehr. In diesem Sinne, Sie sollen schließlich Auslöser der Entsorgung,
aber Sie müssen nicht, dies zu tun in einer kurzlebigen Mode.
Es ist daher Ihre Aufgabe, richtig zu wählen, wenn zum auslösen der Entsorgung,
Basis auf Ihren realen Objekt im Lebenszyklus der Anforderung.
Es gibt nichts hindert Sie mit einem IDisposable in einer langlebigen Art:
Mit diesem neuen Verständnis, jetzt rekapitulieren wir das blog-post
wir können eindeutig feststellen, dass der "fix" initialisiert
HttpClient
einmal, aber nie entsorgen Sie es,das ist, warum wir sehen können, von seiner netstat-Ausgabe,,
die Verbindung bleibt im Status ESTABLISHED was bedeutet, es wurde NICHT richtig geschlossen.
Wenn es geschlossen wäre, seinen Staat wäre in TIME_WAIT statt.
In der Praxis ist es nicht eine große Sache undicht wird nur eine Verbindung geöffnet, nachdem Sie Ihre gesamte Programm endet,
und die blog-poster immer noch einen performance-Gewinn, nach dem Update;
aber noch ist es begrifflich falsch, die Schuld IDisposable und wählen Sie NICHT entsorgen Sie es.
InformationsquelleAutor der Antwort RayLuo
Ich denke, man sollte die Verwendung des singleton-Musters zu vermeiden, erstellen Sie Instanzen der HttpClient und schließen Sie es die ganze Zeit. Wenn Sie verwenden .Net 4.0 können Sie ein Beispiel-code, wie unten beschrieben. für weitere Informationen über singleton-Muster zu überprüfen hier.
Verwenden Sie den code, wie unten beschrieben.
InformationsquelleAutor der Antwort yayadavid