System.Net.WebException:操作已超时

时间:2009-08-01 00:44:09

标签: c# httpwebrequest

我遇到了一个大问题:我需要一次发送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;,但没有帮助。

6 个答案:

答案 0 :(得分:33)

关闭/处置您的WebResponse对象。

答案 1 :(得分:32)

这意味着它所说的。这项行动耗时太长,无法完成。

顺便说一句,看看WebRequest.Timeout,您会看到 您已将超时设置为1/5秒

答案 2 :(得分:26)

我不确定你使用WebClient.UploadValues的第一个代码示例,这还不够,你可以粘贴更多的周围代码吗?关于您的WebRequest代码,这里有两件事情可以解决:

  1. 您只是请求响应的标头**,您永远不会通过打开和读取(结束)ResponseStream来读取响应的主体。因此,WebRequest客户端有助于保持连接处于打开状态,期望您随时请求身体。直到您读取完成的响应主体(它将自动为您关闭流),清理并关闭流(或WebRequest实例)或等待GC执行其操作,您的连接将保持打开状态。

  2. 您拥有与同一主机2的默认最大活动连接数量。这意味着您用完了前两个连接,然后从未丢弃它们,因此您的客户端不是如果有机会在它达到超时之前完成下一个请求(这是毫秒,顺便说一句,所以你把它设置为0.2秒 - 默认应该没问题。)

  3. 如果您不想要响应的正文(或者您刚刚上传或发布了某些内容并且不期待响应),只需关闭流或客户端,它将为您关闭流。

    解决此问题的最简单方法是确保在一次性对象上使用块:

    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,或者只是一个Web浏览器,如果它是一个简单的GET请求。

    **实际上,您实际上是从响应中请求第一块数据,其中包含HTTP标头,以及正文的开头。这就是为什么在从输出流中读取之前可以读取HTTP头信息(例如Content-Encoding,Set-Cookie等)的原因。在您阅读流时,将从服务器检索更多数据。 WebRequest与服务器的连接保持打开状态,直到您到达此流的末尾(因为它不可搜索而有效关闭它),手动关闭它或将其丢弃。 There's more about this here

答案 3 :(得分:0)

我记得由于我传递的数据量,我在使用WCF的过程中遇到了同样的问题。我记得我到处改变了超时,但问题仍然存在。我最后做的是打开连接作为流请求,我需要更改客户端和服务器端,但它以这种方式工作。由于它是一个流连接,服务器一直在读取,直到流结束。

答案 4 :(得分:0)

代理问题可能导致此问题。 IIS webconfig把它放在

<defaultProxy useDefaultCredentials="true" enabled="true">
          <proxy usesystemdefault="True" />
        </defaultProxy>

答案 5 :(得分:0)

我遇到的错误与添加

Task.Delay(2000);

在每个请求中解决了问题