问题描述
为什么下面的代码在第二次(以及后续)运行时会超时?
Why does the following code Timeout the second (and subsequent) time it is run?
代码挂在:
using (Stream objStream = request.GetResponse().GetResponseStream())
然后导致 WebException 表明请求已超时.
and then causes a WebException saying that the request has timed out.
我已经用 WebRequest
和 HttpWebRequest
似乎代码在 request.GetResponse()
这篇文章表明它可能是一个 GC 问题 --> http://www.vbforums.com/showthread.php?t=610043 - 根据这篇文章,如果 Fiddler 在后台打开,问题就会得到缓解.
This post suggests it may be a GC issue --> http://www.vbforums.com/showthread.php?t=610043 - as per this post the issue is mitigated if Fiddler is open in the background.
服务器在那里并且可用于请求.
The server is there and available for requests.
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 是:
Thrown WebException is:
{"操作超时"}[System.Net.WebException]: {"操作超时"}数据:{System.Collections.ListDictionaryInternal}帮助链接:空内部异常:空消息:操作已超时"来源:《系统》StackTrace: " 在 System.Net.HttpWebRequest.GetResponse() 在 IQX.Licensing.License.GetQLMResponse(String URL) 在 C:UsersjdSVNjdProductsDevelopmentJAD.LicensingJAD.LicensingLicense.cs:第 373 行"目标站点:{System.Net.WebResponse GetResponse()}
{"The operation has timed out"} [System.Net.WebException]: {"The operation has timed out"} Data: {System.Collections.ListDictionaryInternal} HelpLink: null InnerException: null Message: "The operation has timed out" Source: "System" StackTrace: " at System.Net.HttpWebRequest.GetResponse() at IQX.Licensing.License.GetQLMResponse(String URL) in C:UsersjdSVNjdProductsDevelopmentJAD.LicensingJAD.LicensingLicense.cs:line 373" TargetSite: {System.Net.WebResponse GetResponse()}
<小时>
更新:好的所以下面的代码现在可以工作了.servicePoint 将超时设置为接近 4 分钟.更改请求对象上的 ServicePoint.ConnectionLeaseTimeout
意味着请求现在在 5000 毫秒后被销毁.感谢大家的帮助以及这两页:
Update: OK So the following code now works. The servicePoint was setting the timeout to be near 4 minutes. Changing ServicePoint.ConnectionLeaseTimeout
on the request object means that the request is now destroyed after 5000ms. Thanks to all for your help and also to these 2 pages:
- http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx
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;
}
推荐答案
在前面的答案之后,我想添加更多的东西.默认情况下 HttpWebRequest
只允许 2 个连接到同一个主机(这是 HTTP 1.1 niceness"),
On the heels of the previous answers, I wanted to add a couple more things. By default HttpWebRequest
allows only 2 connections to the same host (this is HTTP 1.1 "niceness"),
是的,它可以被覆盖,不,我不会告诉你如何在这个问题中,你必须问另一个:)我认为你应该看看这篇文章.
Yes, it can be overriden, no I won't tell you how in this question, you have to ask another one :) I think you ought to look at this post.
我认为您仍然没有完全处理与 HttpWebRequest 连接的所有资源,因此连接池开始发挥作用,这就是问题所在.除非您真的必须这样做,否则我不会尝试与每个服务器的 2 个连接规则作斗争.
I think that you are still not quite disposing of all your resources connected with the HttpWebRequest, so the connection pooling comes into play and that's the problem. I wouldn't try to fight the 2 connections per server rule, unless you really have to.
正如上面提到的海报之一,在这种情况下,Fiddler 对你有点伤害.
As one of the posters above noted, Fiddler is doing you a bit of a disservice in this case.
我会在你的 catch 之后添加一个很好的 finally {}
子句,并确保如上面的帖子所述,所有流都被刷新、关闭并且对请求对象的引用设置为 null.
I'd add a nice finally {}
clause after your catch and make sure that as the above post notes, all streams are flushed, closed and references to the request object are set to null.
如果这有帮助,请告诉我们.
Please let us know if this helps.
这篇关于HttpWebRequest 在第二次调用时超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!