net example create c# .net idisposable webresponse

c# - create - webrequest vb.net example



¿Cómo disponer adecuadamente de una instancia de WebResponse? (6)

Normalmente, uno escribe un código como este para descargar algunos datos utilizando una solicitud web.

using(WebResponse resp = request.GetResponse()) // WebRequest request... using(Stream str = resp.GetResponseStream()) ; // do something with the stream str

Ahora, si se lanza una WebException, la WebException tiene una referencia al objeto WebResponse, que puede o no haber llamado Dispose (dependiendo de dónde haya ocurrido la excepción, o cómo se implementó la clase de respuesta). No lo sé.

Mi pregunta es cómo se supone que uno debe lidiar con esto. Se supone que uno debe codificar de manera muy defensiva y disponer de la respuesta en el objeto WebException (eso sería un poco extraño, ya que WebException no es IDisposible). ¿O se supone que uno debe ignorar esto, accediendo potencialmente a un objeto desechado o nunca desechando un objeto IDisponible? El ejemplo dado en la documentación de MSDN para WebException.Response es totalmente inadecuado.


Estoy bastante seguro de que cuando tiene una declaración de uso, el objeto se elimina, independientemente de cómo salga del bloque de uso (ya sea mediante una excepción, devolución o simplemente avance a través de la función).

Sospecho que encontrará que el objeto dentro de la WebException ya se ha eliminado si lo deja salir del bloque de uso.

Recuerde, desechar un objeto no necesariamente impide acceder a él más tarde. Puede ser impredecible intentar usar métodos en él más adelante, lo que provoca excepciones de su propio comportamiento o muy extraño (y, por lo tanto, no lo recomendaría). Pero aún así, una gran parte del objeto todavía queda atrás para el recolector de basura, incluso si lo desecha, y por lo tanto, todavía es accesible. El propósito de la disposición es, por lo general, limpiar los controladores de recursos (como en este caso las conexiones TCP activas) que, por razones de rendimiento, no se puede dejar por completo hasta que el recolector de basura las encuentre. Solo menciono esto para aclarar que no es mutuamente excluyente para su disposición y la excepción es mantener una referencia a él.


He echado un vistazo rápido a Reflector y ahora puedo decir:

  • WebResponse , al ser una clase abstracta, delega todo su comportamiento de cierre / disposición a sus clases derivadas.
  • HttpWebResponse , siendo la clase derivada que casi con certeza está utilizando aquí, en sus métodos de cierre / eliminación, solo se refiere a la disposición del flujo de respuesta real. El resto del estado de la clase puede dejarse a merced de la GC.

Por lo tanto, es probable que sea seguro hacer lo que quiera con respecto al manejo de excepciones, siempre y cuando:

  • Cuando lea el flujo de respuesta de WebResponse en el bloque try , WebResponse en un bloque using .
  • Si lee el flujo de respuesta de WebException en el bloque catch , enciérrelo también en un bloque using .
  • No hay que preocuparse por deshacerse de WebException sí.

Obtengo casos similares en las conexiones EF DB.

Así que en realidad creo una lista de conexiones.

Al final del juego, los coloco a todos.


Una pregunta muy interesante (aunque vale la pena señalar que el objeto WebResponse se habrá eliminado al salir del uso). Mi intuición es que realmente no importa que tengas una referencia a este objeto WebResponse eliminado siempre y cuando no intentes hacer nada "operativo" con él.

Es probable que aún pueda acceder a ciertas propiedades en la instancia para fines de registro (como ResponseUri) sin obtener una ObjectDisposedException , pero la referencia general de la excepción no está allí, por lo que puede continuar usando la instancia.

Me interesaría ver lo que otros dicen.


HttpWebRequest realiza internamente una secuencia de memoria fuera de la corriente de red subyacente antes de lanzar WebException , por lo que no hay ningún recurso no administrado asociado con WebResponse devuelto por WebException.Response .

Esto hace que sea innecesario llamar a Dispose() en él. De hecho, tratar de deshacerse de WebException.Response puede causarle dolores de cabeza y problemas porque es posible que haya personas que llaman a su código que está intentando leer las propiedades asociadas con él.

Sin embargo, es una buena práctica que deseche todos los objetos IDisposable que posea. Si decide hacerlo, asegúrese de no tener código dependiendo de la capacidad de leer WebException.Response propiedades de WebException.Response y / o su flujo. La mejor manera sería manejar la excepción y lanzar un nuevo tipo de excepción para no filtrar la WebException a la persona que llama cuando sea posible.

Y también considere mudarse a HttpClient que reemplaza a HttpWebRequest .

Descargo de responsabilidad: No hay garantía implícita.


using (var x = GetObject()) { statements; }

es (casi) equivalente a

var x = GetObject(); try { statements; } finally { ((IDisposable)x).Dispose(); }

por lo que su objeto siempre será eliminado.

Esto significa que en tu caso.

try { using (WebResponse resp = request.GetResponse()) { something; } } catch (WebException ex) { DoSomething(ex.Response); }

ex.Response será el mismo objeto que su objeto resp local, que se eliminará cuando llegue al controlador de captura. Esto significa que DoSomething está utilizando un objeto desechado, y probablemente fallará con una ObjectDisposedException.