2011-10-19 5 views
6

Voglio terminare un httpwebrequest quando ci vuole troppo tempo in connessione. qui è solo un codice simaple che ho scritto:Come terminare la connessione HttpWebRequest in C#? Non funziona nemmeno impostare il timeout o readwritetimeout

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); 
      request.Timeout = 5000; 
      request.ReadWriteTimeout = 5000; 
      request.Proxy = new WebProxy("http://" + proxyUsed + "/", true); 
      request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)"; 

      using (WebResponse myResponse = request.GetResponse()) 
      {      
       using (Stream s = myResponse.GetResponseStream()) 
       { 
        s.ReadTimeout = 5000; 
        s.WriteTimeout = 5000; 
        using (StreamReader sr = new StreamReader(s, System.Text.Encoding.UTF8)) 
        {        
         result = sr.ReadToEnd(); 
         httpLink = myResponse.ResponseUri.AbsoluteUri; 
         sr.Close(); 
        } 
        s.Close(); 
       } 
       myResponse.Close(); 
      } 

Tuttavia, a volte la connessione avrà un circa 15 minuti per ottenere la risposta. La situazione è dopo 15 minuti Posso ancora ottenere la risposta ma non il codice sorgente completo dell'URL. Suppongo che la connessione sia troppo lenta per il fatto che l'URL mi risponda un po 'di dati entro il timeout, solo per esempio ricevere 1byte in 5 secondi, quindi non scade il tempo ma è molto lungo. Come posso interrompere la connessione? Grazie :)

risposta

2

Analizza la lettura del flusso e interrompi se il tempo totale è stato troppo lungo.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL); 
request.Timeout = 5000; 
request.ReadWriteTimeout = 5000; 
request.Proxy = new WebProxy("http://" + proxyUsed + "/", true); 
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)";//ahem! :) 
DateTime giveUp = DateTime.UtcNow.AddSeconds(5); 
using (WebResponse myResponse = request.GetResponse()) 
{      
    httpLink = myResponse.ResponseUri.AbsoluteUri; 
    using (Stream s = myResponse.GetResponseStream()) 
    { 
     s.ReadTimeout = 5000; 
     s.WriteTimeout = 5000; 
     char[] buffer = new char[4096]; 
     StringBuilder sb = new StringBuilder() 
     using (StreamReader sr = new StreamReader(s, System.Text.Encoding.UTF8)) 
     {        
      for(int read = sr.Read(buffer, 0, 4096); read != 0; read = sr.Read(buffer, 0, 4096)) 
      { 
       if(DateTime.UtcNow > giveUp) 
        throw new TimeoutException(); 
       sb.Append(buffer, 0, read); 
      } 
      result = sb.ToString(); 
     } 
    } 
} 
4

È possibile che il timeout funzioni effettivamente, ma il thread si blocca quando si tenta di chiudere il flusso. Non so perché succede, ma a volte lo fa. Non ho mai usato ReadToEnd, ma ho incontrato questo quando si utilizza Read.

Ho risolto il problema chiamando Abort sulla richiesta, prima di chiudere lo stream. È un po 'kluge, ma è efficace. Il codice abbreviato sotto mostra la tecnica.

HttpWebResponse response = null; 
StreamReader sr = null; 
try 
{ 
    response = (HttpWebResponse)request.GetResponse(...); 
    Stream s = response.GetResponseStream(); 
    sr = new StreamReader(s, Encoding.UTF8); 
    // do your reading here 
} 
finally 
{ 
    request.Abort(); // !! Yes, abort the request 
    if (sr != null) 
     sr.Dispose(); 
    if (response != null) 
     response.Close(); 
} 

Quello che ho trovato è che il lavoro ReadTimeout e ReadWriteTimeout come previsto. Cioè, quando la lettura è scaduta, l'esecuzione passa effettivamente al blocco finally. E se il request.Abort non è presente, la chiamata a sr.Dispose si bloccherà.