2010-10-28 35 views
1

J'ai le code suivant, et après ~ 60 fois l'appelant (20 connexions simultanées) il commence à expirer. Si je baisse le délai de 10 minutes à 1 minute, ils commencent à attendre environ 34 téléchargements. ce qui donne? Je sais que vous pouvez obtenir si vous ne ferme pas correctement votre réponse, mais je ferme certainement:Timeout avec HttpWebResponse dans .NET

//=============================================================================== 
    /// <summary> 
    /// Executes the request and returns the response as a byte array. Useful if the 
    /// response should return a file. 
    /// </summary> 
    private static byte[] GetResponse(HttpWebRequest webRequest) 
    { 
     //---- declare vars 
     HttpWebResponse response = null; 
     List<byte> buffer = new List<byte>(); 
     int readByte; 

     //---- try to get the response, always wrap it. 
     try 
     { response = webRequest.GetResponse() as HttpWebResponse; } 
     //---- catch all 
     catch (Exception e) 
     { 
      if (response != null) { response.Close(); } 
      throw new ConnectionFailedException("Failed to get a response", e); 
     } 

     try 
     { 
      //---- if the response is ok 
      if (response.StatusCode == HttpStatusCode.OK) 
      { 
       //---- get the response stream 
       using (Stream stream = response.GetResponseStream()) 
       { 
        //---- read each byte, one by one into the byte buffer 
        while ((readByte = stream.ReadByte()) > -1) 
        { 
         buffer.Add((byte)readByte); 
        } 
        //---- close the stream 
        stream.Close(); 
        response.Close(); 
       } 

       //---- return the buffer as a byte array 
       return buffer.ToArray(); 
      } 
      //---- if the request wasn't auth'd 
      else if (response.StatusCode == HttpStatusCode.Forbidden || response.StatusCode == HttpStatusCode.Unauthorized) 
      { 
       if (response != null) { response.Close(); } 
       throw new AuthenticationFailedException(response.StatusDescription); 
      } 
      //---- any other errors 
      else 
      { 
       if (response != null) { response.Close(); } 
       throw new ConnectionFailedException(response.StatusDescription); 
      } 
     } 
     finally { if (response != null) { response.Close(); } } 
    } 
    //=============================================================================== 

pensées?

aussi, je crée avec les deux TimeOut et ReadWriteTimeout fixé à 10 minutes:

// ---- créer la demande web HttpWebRequest webRequest = WebRequest.Create (url) comme HttpWebRequest;

// ---- définir un délai de 10 minutes webRequest.Timeout = 600000; webRequest.ReadWriteTimeout = 600000;

Répondre

3

System.Net.ServicePointManager.DefaultConnectionLimit = 200;

^^ fait.

c'était tout.

1

Que diriez-vous simplifier votre code un peu:

using (var client = new WebClient()) 
{ 
    byte[] result = client.DownloadData("http://example.com"); 
} 
+0

ne peut pas utiliser WebClient. besoin de spécifier des en-têtes personnalisés et l'authentification. –

+0

@bryan, 'client.Headers [" Custom-Header "] =" Valeur personnalisée "' et 'client.Credentials'. –

+0

Je devrais aller de cette façon, mais il y avait d'autres raisons pour lesquelles je ne pouvais pas l'utiliser initialement, je ne me souviens pas de ce qu'ils étaient. une limitation avec WebClient. –

0

propriété Set KeepAlive false par:

webRequest.KeepAlive = false; 

libère la ressource dans la finally.

+0

cela peut être. Je me souviens d'avoir à le faire avant quelque part, maintenant que vous le mentionnez. Je suis en train de tester maintenant. Je vous le ferai savoir. –

+0

gah, ça ne l'a pas réparé. :(va probablement devoir utiliser webclient –

0

Non testé, mais un peu plus propre.

private static byte[] GetResponse(HttpWebRequest webRequest) 
{ 
     using (var response = (HttpWebResponse)webRequest.GetResponse()) 
     { 
      switch (response.StatusCode) 
      { 
       case HttpStatusCode.Forbidden: 
       case HttpStatusCode.Unauthorized: 
        throw new AuthenticationFailedException(response.StatusDescription); 
        break; 
       case HttpStatusCode.OK: 
        break; // to get through 
       default: 
        throw new ConnectionFailedException(response.StatusDescription); 
      } 

      using (Stream stream = response.GetResponseStream()) 
      { 
       // you should really create a large buffer and read chunks. 
       var buffer = new byte[response.ContentLength]; 
       var bytesRead = 0; 
       while (bytesRead < buffer.Length) 
       { 
        var bytes = stream.Read(buffer, bytesRead, buffer.Length - bytesRead); 
        bytesRead += bytes; 
       } 

       return buffer; 
      } 

     } 
} 

Edit:

modifiée de sorte que l'allocation de tampon utilise ContentLength. C'est toujours exact sauf si l'encodage en segments est utilisé.

+0

n'aime pas la chose tampon parce que la longueur n'est pas fiable, vous ne connaissez pas toujours la longueur. Donc l'alternative est de créer une taille de tampon fixe et quand vous le remplissez, créer un autre, copier à redimensionner, etc moins efficace que d'utiliser une liste d'octets et de faire une copie finale –

+0

Vérifiez le code modifié.En outre, l'ajout d'un octet à la fois ne semble pas très efficace. La liste doit allouer un nouveau tampon interne une fois et un moment en le faisant comme vous le souhaitez (vous pouvez réserver une taille pour éviter cela, vérifiez le paramètre de capacité dans le constructeur). – jgauffin