Système.Net.WebException: l'opération est chronométrée

j'ai un gros problème: j'ai besoin d'envoyer 200 objets à la fois et d'éviter les délais d'attente.

while (true)
{

    NameValueCollection data = new NameValueCollection();
    data.Add("mode", nat);

    using (var client = new WebClient())
    {
        byte[] response = client.UploadValues(serverA, data);
        responseData = Encoding.ASCII.GetString(response);

        string[] split = Javab.Split(new[] { '!' },  StringSplitOptions.RemoveEmptyEntries);
        string command = split[0];
        string server = split[1];
        string requestCountStr = split[2];

        switch (command)
        {
            case "check":
                int requestCount = Convert.ToInt32(requestCountStr);

                for (int i = 0; i < requestCount; i++)
                {
                    Uri myUri = new Uri(server);
                    WebRequest request = WebRequest.Create(myUri);
                    request.Timeout = 200000;
                    WebResponse myWebResponse = request.GetResponse();
                }
                break;
        }
    }    
}

Ce qui produit l'erreur:

Unhandled Exception: System.Net.WebException: The operation has timed out  
at System.Net.HttpWebRequest.GetResponse()  
at vir_fu.Program.Main(String[] args)

requestCount boucle fonctionne bien en dehors de mon code de base, mais quand je l'ajoute à mon projet, j'obtiens cette erreur. J'ai essayé la configuration de request.Timeout = 200; mais il n'a pas aidé.

26
demandé sur Alex McMillan 2009-08-01 04:44:08

5 réponses

fermez/éliminez votre objet WebResponse.

33
répondu Joe Chung 2009-08-01 06:12:57

ça veut dire ce que ça dit. L'opération a pris trop de temps.

BTW, regardez WebRequest.Timeout et vous verrez que vous avez configuré votre délai d'attente pour le 1/5 de seconde.

32
répondu John Saunders 2009-08-01 03:59:53

Je ne suis pas sûr de votre premier échantillon de code où vous utilisez WebClient.UploadValues, ce n'est pas vraiment assez pour continuer, pourriez-vous coller plus de votre code d'environnement? En ce qui concerne votre code WebRequest, il y a deux choses en jeu ici:

  1. vous demandez seulement les en-têtes de la réponse**, vous ne lisez jamais le corps de la réponse en ouvrant et en lisant (jusqu'à sa fin) la réponse. Pour cette raison, le client WebRequest laisse la connexion ouverte, vous attend pour demander le corps à tout moment. Jusqu'à ce que vous lisiez le corps de réponse à l'achèvement (qui fermera automatiquement le flux pour vous), nettoyiez et fermiez le flux (ou l'instance de WebRequest) ou attendiez que le GC fasse sa chose, votre connexion restera ouverte.

  2. vous avez un montant maximum par défaut de active connexions au même hôte de 2. Cela signifie que vous utilisez vos deux premières connexions et ne jamais en disposer ainsi votre client n'a pas la possibilité de compléter la requête suivante avant qu'elle n'atteigne son délai d'expiration (qui est de quelques millisecondes, btw, donc vous l'avez réglé à 0,2 seconde - la valeur par défaut devrait être très bien).

si vous ne voulez pas le corps de la réponse (ou si vous venez de télécharger ou de poster quelque chose et n'attendez pas de réponse), fermez simplement le flux, ou le client, qui fermera le flux pour vous.

la façon la plus facile de corriger cela est de s'assurer que vous utilisez en utilisant des blocs sur des objets jetables:

for (int i = 0; i < ops1; i++)
{
    Uri myUri = new Uri(site);
    WebRequest myWebRequest = WebRequest.Create(myUri);
    //myWebRequest.Timeout = 200;
    using (WebResponse myWebResponse = myWebRequest.GetResponse())
    {
        // Do what you want with myWebResponse.Headers.
    } // Your response will be disposed of here
}

une autre solution consiste à autoriser 200 connexions simultanées sur le même hôte. Cependant, à moins que vous n'ayez l'intention de multi-Threader cette opération et que vous ayez besoin de plusieurs connexions simultanées, cela ne vous aidera pas vraiment:

 ServicePointManager.DefaultConnectionLimit = 200;

quand vous obtenez des temps d'arrêt dans le code, la meilleure chose à faire est d'essayer de recréer ce temps d'arrêt en dehors de votre code. Si vous ne pouvez pas, le problème réside probablement dans votre code. J'ai l'habitude de l'utiliser cURL pour cela, ou simplement un navigateur Web si c'est une simple requête GET.

* * en réalité, vous demandez en fait le premier morceau de données de la réponse, qui contient les en-têtes HTTP, et aussi le début du corps. C'est pourquoi il est possible de lire les informations D'en-tête HTTP (telles que Content-Encoding, Set-Cookie, etc.) avant de lire à partir du flux de sortie. Lorsque vous lisez le flux, d'autres données sont extraites du serveur. La connexion de WebRequest au serveur est conservée ouvert jusqu'à ce que vous atteignez la fin de ce flux (fermeture effective comme il n'est pas adressable), fermer manuellement vous-même ou elle est éliminée. Il n'y a plus à ce sujet ici.

26
répondu Matthew Brindley 2013-04-08 19:01:19

je me souviens que j'ai eu le même problème il y a quelques temps en utilisant WCF en raison de la quantité de données que je passais. Je me souviens que j'ai changé les temps morts partout, mais le problème a persisté. Ce que j'ai finalement fait était d'ouvrir la connexion comme requête stream, j'avais besoin de changer le côté client et le côté serveur, mais ça marche comme ça. Comme il s'agissait d'une connexion de flux, le serveur a continué à lire jusqu'à la fin du flux.

0
répondu Freddy 2009-08-01 00:51:31

l'émission de procurations peut causer cela. IIS webconfig mettre cela dans

<defaultProxy useDefaultCredentials="true" enabled="true">
          <proxy usesystemdefault="True" />
        </defaultProxy>
0
répondu Blue Clouds 2018-03-28 17:52:02