2015-10-01 21 views
6

Wenn ich eine .NET WebException fangen, sollte ich die schließen/entsorgen?Sollte WebException.Response.GetResponseStream() close/dises sein?

Die MSDN example schließt oder entsorgt nichts in der Ausnahme.

Viele SOanswers empfehlen, die Antwort und/oder den Stream zu entsorgen.

Ich entsorgte den Strom und dies verursachte große Probleme. Weil GetResponseStream() (immer?/Manchmal?) Dieselbe Instanz zurückgibt. Wenn ich also den Antwortstream abrufe und ihn dann verwerfe, dann werde ich die Exception möglicherweise erneut auf eine andere Ebene werfen, die auch den Antwortstream erhält. Sie wird bereits entsorgt und unlesbar sein und deshalb mehr Ausnahmen auslösen.

+0

Mögliche Duplikate von [Wie ordne ich eine WebResponse-Instanz ordnungsgemäß ab?] (Https://stackoverflow.com/questions/1887314/how-to-properly-dispose-of-a-webresponse-instance) – Deantwo

Antwort

2

Sie sollten diesen Datenstrom entsorgen, da er möglicherweise Ressourcen enthält. Aber entsorgen Sie es erst, wenn Sie damit fertig sind. Hören Sie einfach auf, es zu entsorgen, bevor Sie den Stream nicht mehr benötigen. Lassen Sie den letzten Benutzer des Streams darüber verfügen.

Wahrscheinlich sollten Sie GetResponseStream() nur einmal aufrufen und den Stream explizit umleiten, so dass es klar ist, dass es derselbe Stream ist.

+0

Können Sie teilen eine Quelle für diese Information? Siehst du etwas in MSDN, das dies vorschlägt? Hast du umfangreiche Erfahrung mit "GetResponseStream"? Oder ist es nur eine allgemeine Vermutung, wie es wahrscheinlich funktioniert?Basierend auf meiner Erfahrung ist das Raten mit dieser API nicht gut. – Peter

+0

Wenn Sie keine gegenteiligen Informationen haben, müssen alle verfügbaren Ressourcen entsorgt werden. Auch wenn ihre aktuelle Implementierung es nicht erfordert (und ich sage nicht, dass das hier der Fall ist), könnte sich das in Zukunft ändern. Daher ist Dekompilierungscode keine sehr zuverlässige Antwort. Der GetResponseStream scheint sehr wahrscheinlich Ressourcen zu halten. Wenn Sie die Entsorgung überspringen möchten, müssen Sie sehr sicher sein. – usr

+0

Beachten Sie, dass das Ergebnis katastrophal ist, wenn Sie falsch geraten. Zufällige Ressourcen Erschöpfung, Verlangsamung oder sogar hängt in der Produktion. Ausgelöst durch Last, nicht gefunden während des Entwicklertests (weil es nicht unter Last steht). – usr

5

Eine kurze Antwort ist, dass Sie es nicht entsorgen müssen, obwohl es eine gute Übung ist, alle IDisposable Objekte, die Sie besitzen, zu entsorgen.

In der Tat versucht WebException.Response oder den Strom von ihm zurück entsorgen würde zu Problemen führen, die Sie erwähnt, da Sie Code seine Eigenschaften versucht, die auftreten können in der oberen Verbindungskette der Exception-Handler zu lesen.

Der Grund, warum es nicht sicher zu entsorgen ist, ist HttpWebRequest intern macht einen Speicher-Stream aus dem Netzwerk-Stream, bevor es WebException wirft, und der zugrunde liegende Netzwerk-Stream wurde bereits geschlossen/entsorgt. Es hat also zu diesem Zeitpunkt keine unmanaged Ressource. Ich nehme an, es war eine Entscheidung, die es einfacher macht, mit der Ausnahme umzugehen.

Leider MSDN Dokumentation hat keine Erklärung für dieses Verhalten. Technisch gesehen kann sich die Implementierung in Zukunft ändern, was zu einem Problem in Ihrem Code führt, das den HttpWebResponse und/oder den zugehörigen Stream von WebException nicht enthält, aber es ist sehr unwahrscheinlich, dass dieses Verhalten die Implementierung ändern würde, da viele Anwendungen vom aktuellen Verhalten abhängen.

Ich muss hinzufügen, dass es eine gute Praxis ist, dass Sie IDisposable Objekte, die Sie besitzen, entsorgen müssen. Wenn möglich, verwenden Sie stattdessen die Klasse HttpClient, damit Sie sich nicht mit dieser Situation befassen müssen. Wenn Sie das nicht können, sollten Sie die WebException selbst behandeln und einen neuen Ausnahmetyp auslösen, der WebException nicht dem Aufrufer Ihres Codes aussetzt, sodass Sie nicht in eine Situation geraten, in der ein Aufrufer versucht, auf WebException.Response zuzugreifen, nachdem Sie ihn entsorgt haben .

Haftungsausschluss: Ich arbeite für Microsoft, aber dies entspricht nicht meinem Arbeitgeber oder der Ansicht des .NET Framework-Teams. Keine Garantie impliziert.