2009-03-16 15 views
5

Escribo código C# 2.0 que debe hacer HTTP GET y POST básicos. Estoy usando System.Net.HttpWebRequest para enviar ambos tipos de solicitud y System.Net.HttpWebResponse para recibir ambos. Mi código para GET se parece a:Excepciones non-stop en C#

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}?{1}", 
    URLToHit, 
    queryString)); 
request.Method = "GET"; 
request.Timeout = 1000; // set 1 sec. timeout 
request.ProtocolVersion = HttpVersion.Version11; // use HTTP 1.1 
try 
{ 
    HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
} 
catch(WebException e) 
{ 
    // If I do anything except swallow the exception here, 
    // I end up in some sort of endless loop in which the same WebException 
    // keeps being re-thrown by the GetResponse method. The exception is always 
    // right (ie: in cases when I'm not connected to a network, it gives a 
    // timed out error, etc...), but it should not be re-thrown! 
} 

Y mi código postal es muy similar.

La última línea funciona bien cuando URLToHit devuelve un estado HTTP 200, pero en cualquier otra circunstancia (es decir, estado HTTP no 200, sin conectividad de red, etc.), se lanza una System.Net.WebException (que se espera, de acuerdo con los documentos de MSDN). Sin embargo, mi código nunca progresa más allá de esa línea.

Cuando intento depurar esto, me parece que no puedo pasar o continuar más allá de la última línea. Cuando intento hacerlo, la solicitud se vuelve a emitir y se vuelve a lanzar la excepción.

¿Alguna idea sobre lo que puedo hacer para que la solicitud solo se emita una vez? Nunca he visto algo así en ningún código basado en excepciones, y me he quedado sin ideas. Nada de esto sucede en otras partes de mi código, solo las partes que se ocupan de la funcionalidad y construcciones de System.Net.

Gracias!

(Actualización: añadido try/catch alrededor del método GetRequest)

+0

por favor, publique el try/catch alrededor del código que está tratando – eglasius

+0

Como un lado - puede encontrar 'WebClient' más fácil de usar que' HttpWebRequest'/'HttpWebResponse' - encapsula esto en métodos como' DownloadString' (GET) y 'UploadString' (POST). –

+0

agregó el try/catch alrededor del método GetRequest (que es el que me causa un problema). Intenté todo, y lo único que resuelve mi problema es tragarme la excepción. ¡Ni siquiera puedo volver a lanzar una copia de WebException! Mismo problema con WebClient. – Aaron

Respuesta

1

No hay tal cosa como una excepción "non-stop" en C#. Para controlar lo que ocurre durante una excepción, utiliza un bloque try-catch.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}?{1}", 
    URLToHit, 
    queryString)); 
request.Method = "GET"; 
request.Timeout = 1000; // set 1 sec. timeout 
request.ProtocolVersion = HttpVersion.Version11; // use HTTP 1.1 

try 
{ 
    HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

    // Code here runs if GetResponse() was successful. 
} 
catch (WebException ex) 
{ 
    // Code here runs if GetResponse() failed. 
} 

// Code here is always run unless another exception is thrown. 

La razón por la que no hay "excepciones non-stop" es porque, si no es una excepción, su código no es posible que haga lo que usted pretende. Por ejemplo, ¿qué esperarías que contenga la variable "respuesta"? ¿Qué harías con eso? El bloque try-catch te da un control total sobre esto.

+0

Entendido. Mi problema exacto es que este es un comportamiento muy inesperado. Esta excepción parece ser arrojada una y otra vez, incluso si la atrapo. – Aaron

+0

Lamento haber malinterpretado su pregunta, pero parece que está tratando de pasar inmediatamente después de la llamada "GetResponse()" fallida, como si quisiera que la excepción se ignorara o no se planteara. Su código de muestra no tiene un bloque try-catch.Si no tiene éxito, se lanza una excepción – Cybis

+0

No hay problema. No quiero que se ignore la excepción. Quiero arrojar, limpiar mi marco de pila actual y burbujear para la persona que llama. en su lugar, parece volver a ejecutar el código que causó la excepción y, como resultado, lanzar continuamente la misma excepción. Obviamente, este es un comportamiento incorrecto. – Aaron

1

Tengo exactamente el mismo problema. Aquí es cómo produzco:

 bool shouldRetry = true; 
     do { 
      try 
      { 
       Stream newStream = myHttpWebRequest.GetRequestStream(); 
       newStream.Write(byteArray, 0, byteArray.Length); 
       newStream.Close(); 
       HttpWebResponse response = (HttpWebResponse)myHttpWebRequest.GetResponse(); 
       shouldRetry = false; 
       response.Close(); 
       tries++; 
       status = response.StatusDescription; 
      } 
      catch (WebException e) 
      { 
       tries++; 
       if (tries >= 5) 
       { 
        throw e; 
       } 
       else 
       { 
        Thread.Sleep(1000); 
       } 
      } 
     } while (shouldRetry); 

Para inducir la excepción, he cambiado de mesa de acogida por lo que el URI va a mi localhost que no proporciona ninguna respuesta adecuada.

¡Pero la excepción se lanza constantemente! Si depuro en Visual Studio, se detiene en

throw e; 

con un aviso/cuadro de "excepción no detectada". si presiono "play" para continuar con la depuración, la misma fila arroja la excepción, no puedo avanzar en el código.

Además, no importa DONDE arroje el error. Intenté guardarlo y lanzarlo después del do/while, después de la llamada a la función, etc. La excepción todavía se lanza y está constantemente allí. La única forma de salir es detener el depurador/salir del servidor web. (en localhost el proceso toma el 100% de su CPU), cuando este estado ocurre en el servidor web, IIS se reinicia después de un tiempo.

Aaron, ¿alguna vez resolvió este problema? Necesito esa excepción y no puedo "tragarla".

ACTUALIZACIÓN: 2010-12-16

Este es el código de una función llamada send(). Esa función se llama realmente dentro de un ThreadPool.QueueUserWorkItem de esta manera.

  ThreadPool.QueueUserWorkItem((object state) => 
      { 
       Thread.Sleep(1); 
       try 
       { 
        send(); 
       } 
       catch (Exception e) 
       { 
        throw e; 
       } 
      }); 

Actualmente estoy tratando de averiguar si eso tiene algo que ver con las excepciones sin escalas que eventualmente bloquear el servidor en mi caso. Como dije ... No importa DÓNDE capte la excepción.

ACTUALIZACIÓN: 2010-12-16 (parte 2)

debo hacer NO obtener el error de nunca acabar si evito el uso de ThreadPool.QueueUserWorkItem.

Continuaré investigando ... Pero quizás podría hacerlo sin ThreadPool.QueueUserWorkItem.

ACTUALIZACIÓN: 2010-12-16 (parte 3)

Thread.CurrentThread.Abort(); 

En lugar de error de tiro resuelve mi problema

1

que he visto problemas similares a éste, y por lo general es sólo en el mismo depurador que la línea que lanza la excepción se vuelve a ejecutar, pero esto solo ocurre cuando la excepción finalmente no se detecta.

Dice que solo muestra este comportamiento cuando vuelve a lanzar en el bloque catch. Ya que está volviendo a lanzar la excepción, ¿dónde queda esa excepción que finalmente es atrapada y tratada (es decir, por un controlador de catch que no termina en con un (re) lanzamiento)?

Si la respuesta es "en ninguna parte", ese es su problema: bajo el depurador es probable que vea esta repetición de la línea de lanzamiento de excepción, y cuando se ejecuta normalmente, la aplicación normalmente se bloqueará debido a un excepción no detectada

0

Aquí hay algo de reflexión: el depurador también puede ejecutar código. Por ejemplo, cuando evalúa una propiedad (en un reloj o QuickWatch, o simplemente colocando el mouse sobre su nombre para el valor de la información sobre herramientas), el depurador ejecutará el código subyacente. Y golpee cualquier punto de ruptura que encuentre durante esto. Quizás esta es la causa? ¿Cuáles son los callstacks en las excepciones subsiguientes? ¿Esto también sucede sin un depurador?

1

Otra nota al margen, hay una diferencia entre estos fragmentos de dos códigos:

catch (Exception e) 
{ 
    throw e; 
} 

catch (Exception e) 
{ 
    throw; 
} 

El primer ejemplo en realidad restablecer el seguimiento de la pila en la excepción a la ubicación actual de la pila, el segundo ejemplo mantendrá el vigente rastro de pila Puede ayudarte a depurar tu problema si cambias tu código al segundo ejemplo.