HttpWebRequest истекло время ожидания второго вызова - PullRequest
43 голосов
/ 29 апреля 2011

Почему следующий код выполняет таймаут во второй (и последующий) раз, когда он выполняется?

Код висит на:

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

и затем вызывает исключение WebException, сообщающее, что запрос имеетТайм-аут.

Я пробовал это с WebRequest и HttpWebRequest

Редактировать: Кажется, код падает в request.GetResponse()

Редактировать: Этопост предполагает, что это может быть проблема с GC -> http://www.vbforums.com/showthread.php?t=610043 - согласно этому посту, проблема устранена, если Fiddler открыт в фоновом режиме.

Сервер существует и доступен для запросов.

    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;
    }

Выдано исключение WebException:

{"Время операции истекло"} [System.Net.WebException]: {"Время операции истекло"} Данные: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: null Сообщение: «Тайм-аут операции» Источник: «Система» StackTrace: »в System.Net.HttpWebRequest.GetResponse () \ r \ n в IQX.Licensing.License.GetQLMResponse (URL-адрес строки) в C: \ Users \ jd \ SVN \ jd \ Products \ Development \ JAD.Licensing \ JAD.Licensing \ License.cs: строка 373 "TargetSite: {System.Net.WebResponse GetResponse ()}


Обновление: ОК. Теперь работает следующий код.ServicePoint устанавливает время ожидания около 4 минут.Изменение ServicePoint.ConnectionLeaseTimeout в объекте запроса означает, что запрос теперь уничтожен через 5000 мс.Спасибо всем за вашу помощь, а также за эти 2 страницы:

  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;
    }
    

Ответы [ 7 ]

27 голосов
/ 29 апреля 2011

Вслед за предыдущими ответами я хотел добавить еще пару вещей.По умолчанию HttpWebRequest разрешает только 2 подключения к одному и тому же хосту (это «милость» HTTP 1.1),

Да, это может быть переопределено, нет, я не скажу вам, как в этом вопросе у вас естьчтобы спросить другого :) Я думаю, вы должны посмотреть на этот пост .

Я думаю, что вы все еще не совсем утилизируете все свои ресурсы, связанные с HttpWebRequest, поэтому пул соединений вступает в игру, и в этом проблема.Я бы не стал бороться с двумя соединениями на правило сервера, если только вам это не нужно.

Как заметил один из авторов выше, Fiddler в этом случае оказывает вам некоторую медвежью услугу.

Я бы добавил красивое предложение finally {} после вашего перехвата и убедился бы, что, как указано выше в заметках к записи, все потоки сбрасываются, закрываются, а ссылки на объект запроса устанавливаются в нуль.

Пожалуйстадайте нам знать, если это поможет.

21 голосов
/ 29 апреля 2011

WebResponse, полученный с помощью request.GetReponse(), ДОЛЖЕН быть утилизирован надлежащим образом. Попробуйте это (удаление вызовов request.Abort() и GC.Collect()):

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

Редактировать : Поскольку это все еще не работает, я предлагаю вам проверить это с пустым приложением Windows. Таким образом, вы можете изолировать проблемы app.config или максимальное количество одновременных вызовов для хоста * (вы используете другой объект веб-запроса в другом месте вашего приложения к этому хосту; какой веб-ответ расположен неправильно?).

Надеюсь, это решит вашу проблему, у меня нет идей!

8 голосов
/ 29 апреля 2011

Как вы заявили, запуск fiddler в фоновом режиме уменьшит проблему.Это потому, что сила скрипача закрывает любые ответы.Расширение вышеприведенного поста от Sam BI обеспечит закрытие ответа следующим образом:

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

Также может быть целесообразно установить для прокси нулевое значение, например:

 request.Proxy = Null;

Как.NET Framework будет искать прокси, если вы явно не сделаете этого.Когда fiddler работает, этот эффект будет смягчен, так как прокси-сервер fiddlers будет найден напрямую.

4 голосов
/ 25 января 2017

столкнулся с той же проблемой с таймаутами при последующих запросах к серверу, несмотря на правильное удаление / очистку / закрытие всего. попробуйте сбросить группу соединений, у меня сработало:

myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);

также убедитесь, что вы случайно создаете другие объекты HttpWebRequest / Request в других местах вашего приложения, которые не завершаются должным образом или удаляются, поскольку это увеличит количество соединений в точке обслуживания.

1 голос
/ 12 января 2015

У меня была та же проблема, и я решил ее, убедившись, что я вызываю метод Abort() для каждого из созданных объектов запроса.

0 голосов
/ 05 декабря 2017

Случайно ли вы использовали тестовое приложение с именем WindowsFormsApp по умолчанию N ?У меня была та же проблема, что я потратил неделю на отладку, потому что она работала в моем производственном коде, а не в простом тестовом решении, которое я создавал.В конце концов, я решил, что это поведение уникально для использования имени решения по умолчанию вместо правильно названного решения.

Редактировать: я обнаружил, что моя проблема связана с использованием BitDefender в качестве моего программного обеспечения AV.Программы WindowsFormsApp N были заблокированы.

0 голосов
/ 09 июня 2015

Я установил для http время 10 минут, и оно сработало для меня.

Установка на timeout=infinite заняла больше времени, и моя программа работала в режиме зависания.

...