web-dev-qa-db-fra.com

HttpWebRequest expire au deuxième appel

Pourquoi le code suivant expire-t-il la deuxième (et les suivantes) fois qu'il est exécuté?

Le code se bloque à:

using (Stream objStream = request.GetResponse().GetResponseStream())

puis provoque une WebException indiquant que la demande a expiré.

J'ai essayé ceci avec un WebRequest et HttpWebRequest

Edit: Il semble que le code tombe dans request.GetResponse()

Edit: ce message suggère qu'il peut s'agir d'un problème avec le GC -> http://www.vbforums.com/showthread.php?t=61004 - selon ce message, le problème est atténué si Fiddler est ouvert en arrière-plan.

Le serveur est là et disponible pour les demandes.

    private string GetQLMResponse(string URL)
    {
        HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
        request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
        request.KeepAlive = false;
        request.Timeout = 5000;
        request.Proxy = null;

        // Read stream
        string responseString = String.Empty;
        try
        {
            using (var response = request.GetResponse())
            {
                using (Stream objStream = response.GetResponseStream())
                {
                    using (StreamReader objReader = new StreamReader(objStream))
                    {
                        responseString = objReader.ReadToEnd();
                        objReader.Close();
                    }
                    objStream.Flush();
                    objStream.Close();
                }
                response.Close();
            }
        }
        catch (WebException ex)
        {
            throw new LicenseServerUnavailableException();
        }
        finally
        {
            request.Abort();
            request = null;
            GC.Collect();
        }
        return responseString;
    }

La WebException levée est:

{"L'opération a expiré"} [System.Net.WebException]: {"L'opération a expiré"} Données: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: null Message: "L'opération a expiré" Source: "System" StackTrace: "at System.Net.HttpWebRequest.GetResponse ()\r\n at IQX.Licensing.License.GetQLMResponse (String URL) in C:\Users\jd\SVN\jd\Products\Development\JAD.Licensing\JAD.Licensing\License.cs: ligne 373 "TargetSite: {System.Net.WebResponse GetResponse ()}


Mise à jour: OK Donc, le code suivant fonctionne maintenant. Le servicePoint définissait le délai d'attente à près de 4 minutes. La modification de ServicePoint.ConnectionLeaseTimeout Sur l'objet de demande signifie que la demande est maintenant détruite après 5000 ms. Merci à tous pour votre aide et aussi à ces 2 pages:

  1. http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx
  2. http://msdn.Microsoft.com/en-us/library/6hszazfz (v = VS.80) .aspx

    private string GetQLMResponse(string URL)
    {
        HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
        request.Credentials = new NetworkCredential(Settings.Default.LicenseUser, Settings.Default.LicensePassword);
        request.KeepAlive = false;
        request.Timeout = 5000;
        request.Proxy = null;
    
        request.ServicePoint.ConnectionLeaseTimeout = 5000;
        request.ServicePoint.MaxIdleTime = 5000;
    
        // Read stream
        string responseString = String.Empty;
        try
        {
            using (WebResponse response = request.GetResponse())
            {
                using (Stream objStream = response.GetResponseStream())
                {
                    using (StreamReader objReader = new StreamReader(objStream))
                    {
                        responseString = objReader.ReadToEnd();
                        objReader.Close();
                    }
                    objStream.Flush();
                    objStream.Close();
                }
                response.Close();
            }
        }
        catch (WebException ex)
        {
            throw new LicenseServerUnavailableException();
        }
        finally
        {
            request.Abort();
        }
        return responseString;
    }
    
43
Darbio

Dans la foulée des réponses précédentes, je voulais ajouter quelques éléments supplémentaires. Par défaut, HttpWebRequest n'autorise que 2 connexions au même hôte (c'est la "gentillesse" HTTP 1.1),

Oui, cela peut être annulé, non, je ne vous dirai pas comment dans cette question, vous devez en poser une autre :) Je pense que vous devriez regarder ce post .

Je pense que vous ne disposez pas encore de toutes vos ressources connectées à HttpWebRequest, donc le pool de connexions entre en jeu et c'est le problème. Je n'essaierais pas de combattre les 2 connexions par règle de serveur, sauf si vous y êtes vraiment obligé.

Comme l'a indiqué l'une des affiches ci-dessus, Fiddler vous rend un peu un mauvais service dans ce cas.

J'ajouterais un joli finally {} clause après votre capture et assurez-vous que, comme les notes de publication ci-dessus, tous les flux sont vidés, fermés et les références à l'objet de demande sont définies sur null.

Veuillez nous faire savoir si cela aide.

27
dawebber

Le WebResponse obtenu par request.GetReponse() DOIT être éliminé correctement. Essayez ceci (en supprimant les appels request.Abort() et GC.Collect()):

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   }
}

Edit : Comme cela ne fonctionne toujours pas, je vous suggère de tester cela avec une application Windows vide. De cette façon, vous pouvez isoler les problèmes app.config ou le nombre maximal d'appels simultanés par hôte * (utilisez-vous un autre objet Webrequest ailleurs dans votre application vers cet hôte; quelles réponses Web ne sont pas supprimées correctement?).

J'espère que cela résoudra votre problème, je suis à court d'idées!

  • Voir la réponse de Jon Skeet ici .
21
Sam B

Comme vous l'avez indiqué, l'exécution de fiddler en arrière-plan atténuerait le problème. En effet, la force du violoneux ferme toutes les réponses. S'étendant sur le post ci-dessus de Sam B, je m'assurerais que la réponse est fermée comme suit:

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   } 
   wresponse.close();
}

Il peut également être utile de définir le proxy sur null comme suit:

 request.Proxy = Null;

Comme le framework .NET sortira à la recherche d'un proxy, sauf si vous le faites explicitement. Lorsque le violon est en cours d'exécution, cet effet serait atténué car le proxy du violon serait trouvé directement.

8
Sean Hunter

a rencontré le même problème avec les délais d'attente sur les demandes suivantes au serveur malgré l'élimination/le vidage/la fermeture de tout correctement. essayez de vider votre groupe de connexion, a travaillé pour moi:

myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);

assurez-vous également que vous ne créez pas par inadvertance d'autres objets HttpWebRequest/Request ailleurs dans votre application qui ne sont pas correctement terminés/supprimés, car cela augmentera le nombre de connexions dans le point de service.

5
rdltrr

J'ai eu le même problème, et je l'ai résolu en veillant à appeler la méthode Abort() sur chacun des objets de demande créés.

1
Paul Schneider

Avez-vous par hasard utilisé une application de test avec le nom par défaut de WindowsFormsApp N ? J'ai eu le même problème que j'ai passé une semaine à déboguer car cela fonctionnait dans mon code de production mais pas dans une solution de test simple que je construisais. À la fin, j'ai déterminé que ce comportement était unique à l'utilisation du nom de solution par défaut au lieu d'une solution correctement nommée.

Edit: j'ai découvert que mon problème était lié à l'utilisation de BitDefender comme mon logiciel AV. Les programmes WindowsFormsApp N ont tous été bloqués.

0
oldSchool