HttpWebRequest在第二次调用时超时

Dar*_*bio 43 c# garbage-collection http webrequest httpwebrequest

为什么以下代码超时运行它的第二个(及后续)时间?

代码挂起:

using (Stream objStream = request.GetResponse().GetResponseStream())
Run Code Online (Sandbox Code Playgroud)

然后导致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;
    }
Run Code Online (Sandbox Code Playgroud)

抛出的WebException是:

{"操作已超时"} [System.Net.WebException]:{"操作已超时"}数据:{System.Collections.ListDictionaryInternal} HelpLink:null InnerException:null消息:"操作已超时"来源:"系统"StackTrace:"在System.Net.HttpWebRequest.GetResponse()\ r \n,位于C:\ Users\jd\SVN\_Jd\Products\Development \中的IQX.Licensing.License.GetQLMResponse(String URL) JAD.Licensing\JAD.Licensing\License.cs:第373行"TargetSite:{System.Net.WebResponse GetResponse()}


更新:确定以下代码现在可以正常工作.servicePoint将超时设置为接近4分钟.更改ServicePoint.ConnectionLeaseTimeout请求对象意味着请求现在在5000ms后被销毁.感谢大家的帮助以及这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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

daw*_*ber 28

在之前的答案之后,我想补充一些东西.默认情况下HttpWebRequest,只允许2个连接到同一主机(这是HTTP 1.1"niceness"),

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

我认为您仍然没有完全处理与HttpWebRequest相关的所有资源,因此连接池发挥作用,这就是问题所在.除非你真的需要,否则我不会尝试对每个服务器规则的2个连接进行对抗.

正如上面提到的其中一张海报,Fiddler在这种情况下对你有点不利.

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

如果有帮助,请告诉我们.

  • @dawebber:谢谢,我现在已经使用了`request.ServicePoint`类和设置属性.这也有帮助 - > http://msdn.microsoft.com/en-us/library/6hszazfz(v=VS.80).aspx (2认同)

Sam*_*m B 21

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

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Sea*_*ter 8

正如您所说,在后台运行提琴手可以缓解这个问题.这是因为提琴手力量会关闭任何回应.从Sam BI扩展上述帖子将确保响应如此关闭:

using (var wresponse = request.GetResponse())
{
   using (Stream objStream = wresponse.GetResponseStream())
   {
        // ...
   } 
   wresponse.close();
}
Run Code Online (Sandbox Code Playgroud)

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

 request.Proxy = Null;
Run Code Online (Sandbox Code Playgroud)

因为.NET框架会出去搜索代理,除非你明确地这样做.当fiddler运行时,这种效果会被减轻,因为可以直接找到小提琴代理.


rdl*_*trr 5

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

myRequest.ServicePoint.CloseConnectionGroup(myRequest.ConnectionGroupName);
Run Code Online (Sandbox Code Playgroud)

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