HttpWebResponse застрять во время выполнения в цикле


Я строю этот метод (c#) для получения кода состояния ответа HTTP от URL. когда я запускаю этот метод, он работает нормально, но когда я запускаю его в цикле, в третий раз его застрял. есть зацепка??

 public static string isAlive(string url)
    {
        Console.WriteLine("start: Is Alive Test");
        WebRequest request = WebRequest.Create(url);
        try
        {
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return Convert.ToString((int)response.StatusCode);
        }
        catch(WebException ex)
        {
            HttpWebResponse res  = (HttpWebResponse)ex.Response;
            return Convert.ToString((int)res.StatusCode);
        }
    }

Петля

        for (int i = 0; i < 5; i++)
        {
            string a = isAlive("https://www.yahoo.com/");
            Console.WriteLine(a);
        }
4 4

4 ответа:

Вы не вызываете Dispose на объект HttpWebResponse, что означает, что соединение все еще лежит вокруг. Если вы измените свой код на следующий:

public static string isAlive(string url)
{
   Console.WriteLine("start: Is Alive Test");
   WebRequest request = WebRequest.Create(url);
   try
   {
       using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            return Convert.ToString((int)response.StatusCode);
        }

   }
   catch(WebException ex)
   {
       using(HttpWebResponse res  = (HttpWebResponse)ex.Response)
       {
          return Convert.ToString((int)res.StatusCode);
       }
   }
}

Оператор using неявно вызовет Dispose для вас, который закроет соединение.

Причина, по которой ваш код останавливается после второй итерации, заключается в том, что .Net имеет встроенное максимальное число соединений, которое он откроет для веб-сайта, что по умолчанию равно 2. Это контролируется System.Net.ServicePointManager.DefaultConnectionLimit , который вы можете увеличить должны вам нужно.

Это может быть связано с тем, что вы не закрываете HttpWebResponse. Добавим, наконец, что попробовать поймать, который закрывает ответ. Также закройте ответ WebException в catch.

Используйте "using", и это будет хорошо работать.

        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            return Convert.ToString((int)response.StatusCode);
        }
  • вам нужно обернуть HttpWebResponse var в using оператор, потому что он одноразовый
  • Перед проверкой ex.Response.StatusCode убедитесь, что ex.Статус - ProtocolError
  • а также рассмотрите возможность сделать ваш метод асинхронным из соображений производительности
  • поскольку ваш метод возвращает код состояния, для него может быть более подходящее имя, чем isAlive

Пример:

public static async Task<string> GetStatusCode(string url)
{
    var request = (HttpWebRequest)WebRequest.Create(url);

    try
    {
        using (var response = (HttpWebResponse)await request.GetResponseAsync())
        {
            return response.StatusCode.ToString();
        }
    }
    catch (WebException ex)
    {
        return ex.Status == WebExceptionStatus.ProtocolError ?
                ((HttpWebResponse)e.Response).StatusCode.ToString() : null;
    }
}