【问题标题】:HttpWebRequest times out on second callHttpWebRequest 在第二次调用时超时
【发布时间】:2011-04-29 01:47:22
【问题描述】:

为什么下面的代码在第二次(以及后续)运行时会超时?

代码挂在:

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

然后导致 WebException 表明请求已超时。

我已经用WebRequestHttpWebRequest 尝试过这个

编辑:似乎代码在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} 帮助链接:空 内部异常:空 消息:“操作已超时” 来源:《系统》 StackTrace: " 在 System.Net.HttpWebRequest.GetResponse()\r\n 在 IQX.Licensing.License.GetQLMResponse(String URL) 在 C:\Users\jd\SVN\jd\Products\Development\JAD.Licensing\JAD .Licensing\License.cs:第 373 行" 目标站点:{System.Net.WebResponse GetResponse()}


更新:好的所以下面的代码现在可以工作了。 servicePoint 将超时设置为接近 4 分钟。在请求对象上更改ServicePoint.ConnectionLeaseTimeout 意味着请求现在在 5000 毫秒后被销毁。感谢大家的帮助以及这两页:

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

【问题讨论】:

  • 你有什么理由用gc标记这个?
  • 这篇帖子暗示可能是垃圾回收问题:vbforums.com/showthread.php?t=610043
  • 哦,感谢您发布更新。解决了我的问题。
  • 感谢您发布您的解决方案。今天为我节省了一点时间。

标签: c# http garbage-collection httpwebrequest webrequest


【解决方案1】:

在前面的答案之后,我想添加更多内容。默认情况下HttpWebRequest 只允许 2 个连接到同一主机(这是 HTTP 1.1 “niceness”),

是的,它可以被覆盖,不,我不会告诉你如何在这个问题中,你必须问另一个:) 我认为你应该看看this post

我认为您仍然没有完全处理与 HttpWebRequest 连接的所有资源,因此连接池开始发挥作用,这就是问题所在。除非您真的必须这样做,否则我不会尝试与每个服务器规则中的 2 个连接作斗争。

正如上面提到的海报之一,在这种情况下,Fiddler 对你有点伤害。

我会在你的 catch 之后添加一个很好的 finally {} 子句,并确保正如上面的帖子说明,所有流都被刷新、关闭并且对请求对象的引用设置为 null。

如果这有帮助,请告诉我们。

【讨论】:

  • 谢谢。我曾尝试强制它使用 HTTP 1.0。我尝试将请求设置为空。然后做一个GC.Collect() - 无济于事。
  • @JD,也可以试试netstat -n | find /i "<IPaddress>",其中是服务的IP。它列出了多少次,连接处于什么状态?
  • @JD,尝试关闭 ServicePointManager 上的 TCPKeepAlive,通过设置适当的超时等。我仍然认为这里有些奇怪,服务器不符合 RFC2616 或存在某种它前面有奇怪的反向代理,或者服务器端存在连接限制。
  • @dawebber:谢谢,我现在已经使用request.ServicePoint 类和设置属性让它工作了。这也有帮助 --> msdn.microsoft.com/en-us/library/6hszazfz(v=VS.80).aspx
  • @dawebber:服务器是 IIS 7.5 并且“应该”符合要求。它现在通过将超时更改为 5 秒来工作。感谢您的帮助:)
【解决方案2】:

request.GetReponse() 获得的WebResponse 必须妥善处理。试试这个(删除request.Abort()GC.Collect() 调用):

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

编辑: 由于它仍然不起作用,我建议您使用空的 Windows 应用程序进行测试。这样,您可以隔离 app.config 问题或每个主机的最大并发调用数*(您是否在应用程序中的其他地方使用其他 webrequest 对象到此主机;哪些 webresponse 未正确处理?)。

希望这能解决你的问题,我没有想法!

  • 请参阅 Jon Skeet 的回答 here

【讨论】:

  • 谢谢,但这仍然会导致同样的问题发生。我已经更新了上面的源代码以反映您的建议。
  • AFAIK WebResponse 没有实现 IDisposable。
  • @JD:是的。 WebResponse 类签名:public abstract class WebResponse : MarshalByRefObject, ISerializable, IDisposable (msdn.microsoft.com/en-us/library/…)。但是,WebRequest 没有实现 IDisposable。
  • @JD:你能发布在你的 try-catch 中捕获的异常消息(使用更新的代码)吗?
  • @SamB:我的立场是正确的 - 我在 Intelisense 中看不到 Dispose 方法...只是在上面提出异常。
【解决方案3】:

正如您所说,在后台运行提琴手可以缓解该问题。这是因为提琴手强制关闭任何响应。扩展 Sam B 的上述帖子,我将确保响应关闭,如下所示:

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

还可能值得将代理设置为 null,如下所示:

 request.Proxy = Null;

除非您明确这样做,否则 .NET 框架会搜索代理。当 fiddler 运行时,这种影响会得到缓解,因为 fiddler 代理会直接找到。

【讨论】:

  • 这很奇怪。我能建议的唯一其他事情是来自 Phil Haak 的修复:haacked.com/archive/2004/05/15/…
  • 您的回答对我来说似乎是最不可能的,但事实就是如此 - 我忘记在不同的函数中关闭响应(我什至没有看那里)。
【解决方案4】:

尽管正确处理/刷新/关闭所有内容,但对服务器的后续请求超时也遇到了同样的问题。尝试刷新您的连接组,为我工作:

myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);

另外,请确保您不会无意中在应用程序的其他位置创建其他未正确终止/处置的 HttpWebRequest/Request 对象,因为这会增加服务点中的连接数。

【讨论】:

    【解决方案5】:

    我遇到了同样的问题,我解决了这个问题,确保在创建的每个请求对象上调用 Abort() 方法。

    【讨论】:

      【解决方案6】:

      您是否使用过默认名称为 WindowsFormsAppN 的测试应用程序?我遇到了同样的问题,我花了一周时间进行调试,因为它在我的生产代码中有效,但在我正在构建的简单测试解决方案中无效。最后,我确定这种行为是使用默认解决方案名称而不是正确命名的解决方案所独有的。

      编辑:我发现我的问题与使用 BitDefender 作为我的 AV 软件有关。 WindowsFormsAppN 个程序都被阻止了。

      【讨论】:

        【解决方案7】:

        我阅读了上面标记为答案的帖子,但上面对我并没有真正的工作。 我最终使用 using 标签重写了代码,并在此处添加了其他人推荐的 CloseConnectionGroup 段。最终这就是代码的样子:

        System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(imageUrl);
                        webRequest.AllowWriteStreamBuffering = true;
                        webRequest.Timeout = 30000;
                        webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
                        webRequest.ServicePoint.MaxIdleTime = 5000;
        
                        using (System.Net.WebResponse webResponse = webRequest.GetResponse())
                        {
        
                            using (System.IO.Stream stream = webResponse.GetResponseStream())
                            {
                                image = System.Drawing.Image.FromStream(stream);
                            }
                        }
        
                        webRequest.ServicePoint.CloseConnectionGroup(webRequest.ConnectionGroupName);
                        webRequest = null; 
                    }
        

        【讨论】:

          【解决方案8】:

          添加此内容时与我完成

          myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);
          

          【讨论】:

            【解决方案9】:

            我已将 http 超时设置为 10 分钟,这对我有用。

            设置为timeout=infinite 需要更多时间,我的程序进入挂起模式。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-09-11
              • 1970-01-01
              • 2021-04-02
              相关资源
              最近更新 更多