2009-03-16 5 views
5

Scrivo codice C# 2.0 che deve eseguire GET e POST HTTP di base. Sto usando System.Net.HttpWebRequest per inviare entrambi i tipi di richiesta e System.Net.HttpWebResponse per riceverli entrambi. Il mio codice per GET si presenta come:Eccezioni non stop in 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! 
} 

E il mio codice POST è molto simile.

L'ultima riga funziona correttamente quando URLToHit restituisce uno stato HTTP 200, ma in qualsiasi altra circostanza (ad esempio: non 200 stato HTTP, nessuna connettività di rete, ecc.), Viene generata una System.Net.WebException (che è previsto, secondo i documenti MSDN). Tuttavia, il mio codice non progredisce mai oltre questa linea.

Quando si tenta di eseguire il debug di questo, non riesco a scavalcare o continuare oltre quell'ultima riga. Quando provo a farlo, la richiesta viene nuovamente emessa e l'eccezione viene ri-generata.

Qualche idea su cosa posso fare per fare una richiesta solo una volta? Non ho mai visto nulla di simile accadere in nessun codice basato su eccezioni, e sono fuori di idee. Nulla di simile accade in nessun'altra parte del mio codice, solo le parti che si occupano delle funzionalità e dei costrutti di System.Net.

Grazie!

(Aggiornamento: aggiunto try/catch attorno al metodo GetRequest)

+0

per favore inserisci il try/catch attorno al codice che stai cercando – eglasius

+0

Come parte - potresti trovare 'WebClient' più facile da usare di' HttpWebRequest'/'HttpWebResponse' - lo incapsula in metodi come' DownloadString' (GET) e 'UploadString' (POST). –

+0

aggiunto il try/catch attorno al metodo GetRequest (che è quello che mi sta causando un problema). Ho provato di tutto, e l'unica cosa che risolve il mio problema è di ingoiare l'eccezione. Non riesco nemmeno a rilanciare una copia di WebException! Lo stesso problema con WebClient. – Aaron

risposta

1

Non c'è cosa come un eccezione "non-stop" in C#. Per controllare cosa succede durante un'eccezione, usi un blocco 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 ragione non ci sono "eccezioni non-stop" è perché, se v'è un'eccezione, il codice non può assolutamente fare quello che intendeva. Ad esempio, cosa ti aspetteresti che la variabile "risposta" contenga? Cosa ne faresti? Il blocco try-catch ti dà il pieno controllo su questo.

+0

Capito. Il mio problema esatto è che questo è un comportamento molto inaspettato. Questa eccezione sembra essere lanciata più e più volte, anche se lo capisco. – Aaron

+0

Mi dispiace se ho frainteso la tua domanda, ma sembra che tu stia tentando di passare immediatamente dopo la chiamata "GetResponse()" fallita, come se volessi che l'eccezione fosse ignorata o non aumentata del tutto. Il tuo codice di esempio non ha un blocco try-catch.Se non riesce, viene generata un'eccezione – Cybis

+0

Nessun problema. Non voglio che l'eccezione sia ignorata. Voglio che passi, ripulisci il mio attuale stack frame e mostro al chiamante. invece, sembra rieseguire il codice che ha causato l'eccezione e, di conseguenza, genera continuamente la stessa eccezione. Ovviamente, questo è un comportamento scorretto. – Aaron

1

Ho lo stesso identico problema. Ecco come produco è:

 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); 

per indurre l'eccezione, ho cambiato la mia tabella degli host in modo che l'URI va al mio localhost che non fornisce alcuna risposta adeguata.

Ma l'eccezione viene costantemente lanciata! Se eseguo il debug in Visual Studio, si arresta a

throw e; 

con un avviso/casella "eccezione non rilevata". se premo "play" per continuare il debug, la stessa riga genera un'eccezione, non posso andare avanti nel codice.

Inoltre, non importa DOVE ho generato l'errore. Ho provato a salvarlo e lanciarlo dopo il do/while, dopo la chiamata alla funzione, ecc. L'eccezione è ancora generata ed è costantemente presente. L'unico modo per andarsene è fermare il debugger/exit webserver. (su localhost il processo prende il 100% della sua CPU), quando questo stato si verifica sull'host webserver, IIS viene riavviato dopo un po '.

Aaron, hai mai risolto questo problema? Ho bisogno di quell'eccezione e non posso "inghiottirla".

UPDATE: 2010-12-16

Questo codice è in una funzione chiamata send(). Quella funzione è effettivamente chiamata all'interno di un oggetto ThreadPool.QueueUserWork come questo.

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

Attualmente sto cercando di scoprire se questo ha qualcosa a che fare con le eccezioni non-stop che alla fine cadere il server nel mio caso. Come ho detto ... non importa dove rilevo l'eccezione.

UPDATE: 2010-12-16 (parte 2)

faccio NON ottenere l'errore senza fine se meglio cercare di evitare ThreadPool.QueueUserWorkItem.

Io continuerò a studiare .. Ma forse avrei potuto gestire senza ThreadPool.QueueUserWorkItem.

UPDATE: 2010-12-16 (parte 3)

Thread.CurrentThread.Abort(); 

Invece di errore di lancio risolve il mio problema

1

ho visto problemi simili a questo, e di solito è solo in il debugger stesso che la riga che lancia l'eccezione viene rieseguita, ma ciò accade solo quando l'eccezione non è definitiva.

Si dice che essa presenta solo questo comportamento quando si ri-lancio nel blocco catch. Dal momento che stai rilanciando l'eccezione, dove questa eccezione finirà per essere scoperta e gestita (ad esempio da un gestore catch che non termina con un (ri) lancio)?

Se la risposta è "da nessuna parte", allora questo è il tuo problema: sotto il debugger è probabile che tu veda questa riattivazione della linea di lancio delle eccezioni, e quando viene eseguito normalmente, l'applicazione andrà di solito in crash a causa di un eccezione non rilevata.

0

Ecco alcuni spunti di riflessione: il debugger può anche eseguire il codice. Ad esempio, quando si valuta una proprietà (in un orologio, o QuickWatch, o anche solo si passa il mouse sopra il suo nome per il tooltip del valore), il debugger eseguirà il codice sottostante. E colpisci tutti i punti di interruzione che incontra durante questo. Forse questa è la causa? Quali sono i blocchi di chiamata nelle successive eccezioni? Questo succede anche senza un debugger?

1

Un'altra nota di lato, v'è una differenza tra questi frammenti di due codici:

catch (Exception e) 
{ 
    throw e; 
} 

catch (Exception e) 
{ 
    throw; 
} 

Il primo esempio effettivamente reimpostare la traccia stack l'eccezione alla posizione dello stack corrente, il secondo esempio manterrà l'attuale traccia dello stack. Potrebbe aiutarti a eseguire il debug del problema se passi il codice al secondo esempio.