【问题标题】:C# HttpWebRequest times out after two server 500 errorsC# HttpWebRequest 在两次服务器 500 错误后超时
【发布时间】:2011-05-01 07:05:19
【问题描述】:

由于“(500) 内部服务器错误 500”,我创建了两个引发异常的 C# HttpWebRequest 后,第三次尝试引发了超时异常。为什么不抛出另一个 (500) Internal Server Error 异常?

当我重新启动我的应用程序时,它会引发两个 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);
        }
    }
}

更新

感谢大家的帮助。我没能解决这个问题。

dispose 方法现在消失了。

我已将 HttpWebRequest httpRequest、HttpWebResponse webResponse 和 Stream requestStream 设为本地,并使用以下 using 语句:

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 没有得到 abort()'ed。在 catch() 块中我添加了 httpRequest.abort(),现在它可以正常工作了。

【问题讨论】:

  • Dispose 方法是我见过的最糟糕的方法
  • 那么在进行了这些更改之后,您看到了什么行为?完全一样吗?
  • 是的,完全一样。

标签: c# httpwebrequest


【解决方案1】:

HTTP 协议定义了同一服务器只能同时建立两个连接。读取成功或不成功后关闭responseStream

【讨论】:

  • 我现在已将 responseStream 包装在 using 语句中(请参阅第一篇文章中的更新)。够了吗?
  • 是的,我认为这是连接松动而不关闭的地方。
  • 奇怪,我把 responseStream 放到 using 块,仍然超时。
【解决方案2】:

怀疑这是问题所在:

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

您不会丢弃任何这些一次性物品。这意味着与 Web 服务器的连接将一直保持到最终确定为止,因此连接池(每个服务器有两个连接)将不允许任何其他请求。

我建议:

  • 您将 GetResponse 调用从请求流的 using 语句中移出
  • 您删除了对请求流的FlushClose 的显式调用(处理它就足够了)
  • 你可以创建 webResponsewebRequest 局部变量而不是实例变量,除非你以后真的需要它们,在这种情况下你应该在你的 Dispose 方法中处理它们。
  • 您对WebResponseStreamStreamReader 使用using 语句。 (最后一个不是绝对必要的,因为处理流就足够了。)
  • 除非你真的需要,否则你让GetPages 不实现IDisposable

【讨论】:

  • 你不认为这是他的Dispose方法吗? :)
  • @koen:嗯……这让我很吃惊。有可能是因为抛出了异常,所以它没有处理响应。您可能会捕获 WebException 并在其中处理响应...但是如果您确实必须这样做,那就太可怕了:(
  • @jon:可以看一下整个方法吗? (我在第一篇文章中添加了另一个更新)
  • @koen:我没有发现你关闭了保持活动功能。越来越好奇。恐怕我现在没有时间尝试重现它:(
  • @jon:我不得不在 catch 块中使用 Abort() 方法手动中止 httpRequest。非常感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
相关资源
最近更新 更多