Подтвердить что ты не робот

С# HttpWebRequest истекает после двух ошибок сервера 500

После того, как я создаю два С# HttpWebRequests, которые генерируют исключение из-за "(500) Internal Server Error 500", третья попытка выбрасывает исключение тайм-аута. Почему он не выбрасывает другое (500) исключение внутренней ошибки сервера?

Когда я перезапускаю приложение, он выдает две 500 ошибок и затем снова запускает тайм-аут.

Это мой код:

GetPages GetPages = new GetPages();
string test = GetPages.GetPage(); /* Exception: (500) Internal Server Error */
GetPages.Dispose();

GetPages GetPages = new GetPages();
string test = GetPages.GetPage();  /* Exception: (500) Internal Server Error */
GetPages.Dispose();

GetPages GetPages = new GetPages();
string test = GetPages.GetPage();  /* Exception: time out, why? */
GetPages.Dispose();

Это класс GetPages и метод GetPage:

namespace MyNamespace
{
    class GetPages
    {
        public string GetPage()
        {
            this.httpRequest = (HttpWebRequest)WebRequest.Create("http://myurl");

            try
            {
                StringBuilder postData = new StringBuilder(100);
                postData.Append("test=test");
                byte[] dataArray = Encoding.UTF8.GetBytes(postData.ToString());

                httpRequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
                httpRequest.KeepAlive = false;
                httpRequest.Proxy = null;
                httpRequest.Method = "POST";
                httpRequest.Timeout = 10;
                httpRequest.ContentType = "application/x-www-form-urlencoded";

                httpRequest.ContentLength = dataArray.Length;

                using (this.requestStream = httpRequest.GetRequestStream())
                {
                    requestStream.Write(dataArray, 0, dataArray.Length);
                    requestStream.Flush();
                    requestStream.Close();

                    this.webResponse = (HttpWebResponse)httpRequest.GetResponse();

                    Stream responseStream = webResponse.GetResponseStream();
                    StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8);
                    String responseString = responseReader.ReadToEnd();


                    MessageBox.Show(responseString);
                    return responseString;
                }
            }

            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return "FAIL";
            }
        }

        public void Dispose()
        {
            System.GC.SuppressFinalize(this);
        }
    }
}

UPDATE

Спасибо всем за помощь. Я не смог решить проблему.

Теперь метод удаления исчез.

Я сделал HttpWebRequest httpRequest, HttpWebResponse webResponse и Stream requestStream local и использую следующие операторы:

using (webResponse = (HttpWebResponse)httpRequest.GetResponse())
{
    using (Stream responseStream = webResponse.GetResponseStream())
    {
        using (StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8))
        {
            responseString = responseReader.ReadToEnd();
        }
    }
}

Другое обновление

Теперь это весь метод GetPage:

public string GetPage()
{
    HttpWebRequest httpRequest;
    HttpWebResponse webResponse;
    Stream requestStream;

    try
    {
        StringBuilder postData = new StringBuilder(100);
        postData.Append("test=test");
        byte[] dataArray = Encoding.UTF8.GetBytes(postData.ToString());

        httpRequest = (HttpWebRequest)WebRequest.Create("http://myurl");

        httpRequest.Proxy = null;
        httpRequest.Method = "POST";
        httpRequest.Timeout = 10;
        httpRequest.ContentType = "application/x-www-form-urlencoded";

        httpRequest.ContentLength = dataArray.Length;

        using (requestStream = httpRequest.GetRequestStream())
        {
            /* this is never reached when the time out exception starts 
            so the error seems to be related to too many GetRequestStreams */

            requestStream.Write(dataArray, 0, dataArray.Length);

            webResponse = (HttpWebResponse)httpRequest.GetResponse();

            /* this is never reached when the 500 server error occurs */

            String responseString = "";
            using (Stream responseStream = webResponse.GetResponseStream())
            {
                using (StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8))
                {
                    responseString = responseReader.ReadToEnd();
                    return responseString;
                }
            }
        }
    }

    catch (Exception e)
    {
        return "FAIL";
    }

    return "...";
}

** РЕШЕННО!! ** httpRequest не прерывался(). В блоке catch() я добавил httpRequest.abort(), теперь он работает правильно.

4b9b3361

Ответ 1

Я подозреваю, что это проблема:

this.webResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream, Encoding.UTF8);
String responseString = responseReader.ReadToEnd();

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

Я предлагаю, чтобы:

  • Вы перемещаете вызов GetResponse из инструкции using для потока запросов
  • Вы удаляете явные вызовы Flush и Close для потока запросов (удаление из него достаточно)
  • Вместо локальных переменных вместо переменных экземпляра вы делаете локальные переменные webResponse и webRequest, если они вам действительно не нужны, и в этом случае вы должны избавиться от них в вашем методе Dispose.
  • Вы используете выражения using для webResponse, Stream и StreamReader. (Последнее не является строго необходимым, так как распоряжение потоком достаточно хорошо.)
  • Вы делаете GetPages не реализовывать IDisposable, если вам это действительно не нужно.

Ответ 2

Протокол HTTP определяет, что только одно соединение может быть выполнено одновременно с одним и тем же сервером. Закройте responseStream после успешного или неудачного чтения.