c# - HttpWebRequest se agota en la segunda llamada
garbage-collection (7)
¿Por qué el siguiente código Timeout la segunda (y posterior) vez que se ejecuta?
El código cuelga en:
using (Stream objStream = request.GetResponse().GetResponseStream())
y luego causa una WebException que dice que la solicitud ha expirado.
Lo he intentado con WebRequest
y HttpWebRequest
Editar: parece que el código está cayendo en request.GetResponse()
Editar: esta publicación sugiere que puede tratarse de un problema de GC -> http://www.vbforums.com/showthread.php?t=610043 - según esta publicación, el problema se mitiga si Fiddler está abierto en segundo plano.
El servidor está ahí y disponible para solicitudes.
private string GetQLMResponse(string URL)
{
HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
// Read stream
string responseString = String.Empty;
try
{
using (var response = request.GetResponse())
{
using (Stream objStream = response.GetResponseStream())
{
using (StreamReader objReader = new StreamReader(objStream))
{
responseString = objReader.ReadToEnd();
objReader.Close();
}
objStream.Flush();
objStream.Close();
}
response.Close();
}
}
catch (WebException ex)
{
throw new LicenseServerUnavailableException();
}
finally
{
request.Abort();
request = null;
GC.Collect();
}
return responseString;
}
Thrown WebException es:
{"La operación ha expirado"} [System.Net.WebException]: {"La operación ha expirado"} Datos: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: null Mensaje: "La operación ha expirado" Fuente: "System" StackTrace: "en System.Net.HttpWebRequest.GetResponse () / r / n en IQX.Licensing.License.GetQLMResponse (String URL) en C: / Users / jd / SVN / jd / Products / Development / JAD.Licensing / JAD.Licensing / License.cs: línea 373 "TargetSite: {System.Net.WebResponse GetResponse ()}
Actualización: OK Entonces el siguiente código ahora funciona. El ServicePoint estaba configurando el tiempo de espera para estar cerca de 4 minutos. Cambiar ServicePoint.ConnectionLeaseTimeout
en el objeto de solicitud significa que la solicitud ahora se destruye después de 5000 ms. Gracias a todos por su ayuda y también a estas 2 páginas:
- http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx
http://msdn.microsoft.com/en-us/library/6hszazfz(v=VS.80).aspx
private string GetQLMResponse(string URL) { HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest; request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword); request.KeepAlive = false; request.Timeout = 5000; request.Proxy = null; request.ServicePoint.ConnectionLeaseTimeout = 5000; request.ServicePoint.MaxIdleTime = 5000; // Read stream string responseString = String.Empty; try { using (WebResponse response = request.GetResponse()) { using (Stream objStream = response.GetResponseStream()) { using (StreamReader objReader = new StreamReader(objStream)) { responseString = objReader.ReadToEnd(); objReader.Close(); } objStream.Flush(); objStream.Close(); } response.Close(); } } catch (WebException ex) { throw new LicenseServerUnavailableException(); } finally { request.Abort(); } return responseString; }
Como ha indicado, ejecutar el violín en segundo plano mitigaría el problema. Esto se debe a que la fuerza del violín cierra cualquier respuesta. Extendiéndose en la publicación anterior de Sam BI se aseguraría de que la respuesta se cierre así:
using (var wresponse = request.GetResponse())
{
using (Stream objStream = wresponse.GetResponseStream())
{
// ...
}
wresponse.close();
}
También puede valer la pena configurar el proxy para que anule así:
request.Proxy = Null;
Como el .NET Framework saldrá en busca de un proxy a menos que explícitamente hagas esto. Cuando Fiddler se está ejecutando, este efecto se mitigaría ya que los fiddlers proxy se encontrarían directamente.
Configuré el tiempo de http en 10 minutos y funcionó para mí.
Configuración para timeout=infinite
tomaba más tiempo y mi programa entraba en modo colgado.
La WebResponse
obtenida por request.GetReponse()
DEBE eliminarse correctamente. Pruebe esto (eliminando llamadas request.Abort()
y GC.Collect()
):
using (var wresponse = request.GetResponse())
{
using (Stream objStream = wresponse.GetResponseStream())
{
// ...
}
}
Editar : Dado que todavía no funciona, le sugiero que pruebe esto con una aplicación de Windows vacía. De esta forma, podría aislar los problemas de aplicación o configuración o las llamadas concurrentes máximas por host * (¿está utilizando otro objeto webrequest en otro lugar de su aplicación en este host, qué respuesta web no está dispuesta correctamente?).
Espero que esto resuelva tu problema, ¡me he quedado sin ideas!
- Vea la respuesta de Jon Skeet here .
Por casualidad, ¿estaba usando una aplicación de prueba con el nombre predeterminado de WindowsFormsApp N ? Tuve el mismo problema que pasé una semana depurando porque funcionaba en mi código de producción pero no en una solución de prueba simple que estaba construyendo. Al final, determiné que este comportamiento era exclusivo de usar el nombre de solución predeterminado en lugar de una solución con el nombre adecuado.
Editar: Descubrí que mi problema estaba relacionado con el uso de BitDefender como mi software AV. Todos los programas de WindowsFormsApp N fueron bloqueados.
Siguiendo los pasos de las respuestas anteriores, quería agregar un par de cosas más. Por defecto, HttpWebRequest
permite solo 2 conexiones al mismo host (esto es HTTP 1.1 "niceness"),
Sí, puede ser anulado, no, no te diré cómo en esta pregunta, tienes que preguntarle a otro :) Creo que deberías mirar esta publicación .
Creo que todavía no está desechando todos sus recursos conectados con HttpWebRequest, por lo que la agrupación de conexiones entra en juego y ese es el problema. No trataría de luchar contra las 2 conexiones por regla de servidor, a menos que realmente deba hacerlo.
Como uno de los carteles mencionados anteriormente, Fiddler te está haciendo un poco daño en este caso.
Agregaría una buena cláusula finally {}
final después de su captura y me aseguraré de que, como se indica en las notas anteriores, todas las transmisiones se vacían, se cierran y las referencias al objeto de solicitud se establecen como nulas.
Por favor, háganos saber si esto ayuda.
Tuve el mismo problema, y lo resolví asegurando que llame al método Abort()
en cada uno de los objetos de solicitud creados.
se encontró con el mismo problema con los tiempos de espera en solicitudes posteriores al servidor a pesar de disponer / enjuagar / cerrar todo correctamente. Prueba a enjuagar tu grupo de conexión, funcionó para mí:
myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);
Además, asegúrese de no crear inadvertidamente otros objetos HttpWebRequest / Request en otra parte de su aplicación que no estén finalizados o desechados correctamente, ya que esto aumentará la cantidad de conexiones en el Punto de Servicio.