System.Net.WebException:操作已超时
Posted
技术标签:
【中文标题】System.Net.WebException:操作已超时【英文标题】:System.Net.WebException: The operation has timed out 【发布时间】:2009-08-01 00:44:08 【问题描述】:我有一个大问题:我需要一次发送 200 个对象并避免超时。
while (true)
NameValueCollection data = new NameValueCollection();
data.Add("mode", nat);
using (var client = new WebClient())
byte[] response = client.UploadValues(serverA, data);
responseData = Encoding.ASCII.GetString(response);
string[] split = Javab.Split(new[] '!' , StringSplitOptions.RemoveEmptyEntries);
string command = split[0];
string server = split[1];
string requestCountStr = split[2];
switch (command)
case "check":
int requestCount = Convert.ToInt32(requestCountStr);
for (int i = 0; i < requestCount; i++)
Uri myUri = new Uri(server);
WebRequest request = WebRequest.Create(myUri);
request.Timeout = 200000;
WebResponse myWebResponse = request.GetResponse();
break;
这会产生错误:
Unhandled Exception: System.Net.WebException: The operation has timed out
at System.Net.HttpWebRequest.GetResponse()
at vir_fu.Program.Main(String[] args)
requestCount
循环在我的基本代码之外工作正常,但是当我将它添加到我的项目时,我得到了这个错误。我尝试设置request.Timeout = 200;
,但没有帮助。
【问题讨论】:
顺便说一句,当您发布代码时,请尝试发布真实代码。您的代码无法编译:WebRequest
构造函数是protected
。如果您使用“// ...”代替“...”也会很方便。
【参考方案1】:
它的意思是它所说的。操作完成时间过长。
顺便说一句,看看WebRequest.Timeout,您会发现您已将超时设置为 1/5 秒。
【讨论】:
一个有价值的指南.. 谢谢!!【参考方案2】:关闭/释放您的 WebResponse 对象。
【讨论】:
关闭/处理没有帮助【参考方案3】:我不确定您使用 WebClient.UploadValues 的第一个代码示例,这还不够,您能粘贴更多周围的代码吗?关于您的 WebRequest 代码,这里有两件事在起作用:
您只是请求响应的标头**,您永远不会通过打开和读取(到其末尾)ResponseStream 来读取响应的正文。因此,WebRequest 客户端有助于保持连接打开,期待您随时请求正文。在您读取响应正文完成(它将自动为您关闭流)、清理并关闭流(或 WebRequest 实例)或等待 GC 完成它的操作之前,您的连接将保持打开状态。
您与同一主机的默认最大 活动 连接数量为 2。这意味着您用完前两个连接,然后永远不会丢弃它们,这样您的客户端就不会有机会在超时之前完成下一个请求(这是毫秒,顺便说一句,所以您已将其设置为 0.2 秒 - 默认值应该没问题)。
如果您不想要响应的正文(或者您刚刚上传或发布了某些内容并且不希望得到响应),只需关闭流或客户端,它会为您关闭流。
解决此问题的最简单方法是确保在一次性对象上使用使用块:
for (int i = 0; i < ops1; i++)
Uri myUri = new Uri(site);
WebRequest myWebRequest = WebRequest.Create(myUri);
//myWebRequest.Timeout = 200;
using (WebResponse myWebResponse = myWebRequest.GetResponse())
// Do what you want with myWebResponse.Headers.
// Your response will be disposed of here
另一个解决方案是允许 200 个并发连接到同一主机。但是,除非您计划对此操作进行多线程处理,否则您需要多个并发连接,否则这对您没有帮助:
ServicePointManager.DefaultConnectionLimit = 200;
当您在代码中遇到超时时,最好的办法是尝试在您的代码之外重新创建该超时。如果不能,问题可能出在您的代码上。我通常为此使用cURL,或者如果它是一个简单的 GET 请求,则只使用一个网络浏览器。
** 实际上,您实际上是从响应中请求第一块数据,其中包含 HTTP 标头以及正文的开头。这就是为什么可以在从输出流中读取之前读取 HTTP 标头信息(例如 Content-Encoding、Set-Cookie 等)的原因。当您读取流时,会从服务器检索更多数据。 WebRequest 与服务器的连接保持打开状态,直到您到达此流的末尾(有效地关闭它,因为它不可搜索),您自己手动关闭它或将其处理掉。 There's more about this here.
【讨论】:
@Matthew:你确定要发送HEAD
吗?我想我从未见过这种情况。
对不起,我不是指 HEAD(HEAD 是您请求 only 标头的地方),我的意思是初始响应仅包含标头(这是您通常的如果您刚刚发送了 HEAD 请求,请获取)。我已经编辑以纠正我的错误。
@Matthew:又是什么让你认为响应只包含标题?您是否建议在调用 GetRequestStream
时客户端和服务器之间存在另一个数据包交换?
嗨,马修 B,谢谢您的回复,好的,我的代码这样做: 1 - 开始时(真)//正确工作 1 - 将数据发布到 serverA//正确工作 2 - 接收代码//正确工作 3 - 使用开关(代码)//正确工作 4 - 向 serverB 发送 GET 请求 // 问题在这里 5 - 睡眠 2 分钟 6 - while() 结束;
也许应该改为 // Do what you want with myWebResponse.Headers
而不是 // Do what you want with the HEAD
。这可能不会让读者感到困惑。【参考方案4】:
代理问题可能会导致此问题。 IIS webconfig 把这个放在
<defaultProxy useDefaultCredentials="true" enabled="true">
<proxy usesystemdefault="True" />
</defaultProxy>
【讨论】:
【参考方案5】:我记得我在使用 WCF 时遇到了同样的问题,因为我传递的数据量很大。我记得我到处都更改了超时,但问题仍然存在。我最终所做的是将连接作为流请求打开,我需要更改客户端和服务器端,但它是这样工作的。由于是流连接,服务器一直读取直到流结束。
【讨论】:
【参考方案6】:我遇到了和添加一样的错误
Task.Delay(2000);
在每个请求中都解决了问题
【讨论】:
虽然这种类型的解决方案实际上可能有效,但我不推荐它。这会通过强制每次迭代花费 2 秒人为地减慢该过程。有 200 个项目要处理,这意味着需要 6 分钟以上才能完成,并且并不能真正解决超时的根本问题。我将专注于控制上面建议的流,仅在必要时保持连接打开。这应该允许您的代码以更高的性能水平执行。以上是关于System.Net.WebException:操作已超时的主要内容,如果未能解决你的问题,请参考以下文章
System.Net.WebException:无法解析远程名称:
System.Net.WebException HTTP 状态码
System.Net.WebException:请求被中止:请求被取消