System.Net.WebException: The operation has timed out

落花浮王杯 提交于 2020-01-11 15:47:51

问题


I have a big problem: I need to send 200 objects at once and avoid timeouts.

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

This produces the error:

Unhandled Exception: System.Net.WebException: The operation has timed out  
at System.Net.HttpWebRequest.GetResponse()  
at vir_fu.Program.Main(String[] args)

The requestCount loop works fine outside my base code but when I add it to my project I get this error. I have tried setting request.Timeout = 200; but it didn't help.


回答1:


Close/dispose your WebResponse object.




回答2:


It means what it says. The operation took too long to complete.

BTW, look at WebRequest.Timeout and you'll see that you've set your timeout for 1/5 second.




回答3:


I'm not sure about your first code sample where you use WebClient.UploadValues, it's not really enough to go on, could you paste more of your surrounding code? Regarding your WebRequest code, there are two things at play here:

  1. You're only requesting the headers of the response**, you never read the body of the response by opening and reading (to its end) the ResponseStream. Because of this, the WebRequest client helpfully leaves the connection open, expecting you to request the body at any moment. Until you either read the response body to completion (which will automatically close the stream for you), clean up and close the stream (or the WebRequest instance) or wait for the GC to do its thing, your connection will remain open.

  2. You have a default maximum amount of active connections to the same host of 2. This means you use up your first two connections and then never dispose of them so your client isn't given the chance to complete the next request before it reaches its timeout (which is milliseconds, btw, so you've set it to 0.2 seconds - the default should be fine).

If you don't want the body of the response (or you've just uploaded or POSTed something and aren't expecting a response), simply close the stream, or the client, which will close the stream for you.

The easiest way to fix this is to make sure you use using blocks on disposable objects:

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
}

Another solution is to allow 200 concurrent connections to the same host. However, unless you're planning to multi-thread this operation so you'd need multiple, concurrent connections, this won't really help you:

 ServicePointManager.DefaultConnectionLimit = 200;

When you're getting timeouts within code, the best thing to do is try to recreate that timeout outside of your code. If you can't, the problem probably lies with your code. I usually use cURL for that, or just a web browser if it's a simple GET request.

** In reality, you're actually requesting the first chunk of data from the response, which contains the HTTP headers, and also the start of the body. This is why it's possible to read HTTP header info (such as Content-Encoding, Set-Cookie etc) before reading from the output stream. As you read the stream, further data is retrieved from the server. WebRequest's connection to the server is kept open until you reach the end of this stream (effectively closing it as it's not seekable), manually close it yourself or it is disposed of. There's more about this here.




回答4:


I remember I had the same problem a while back using WCF due the quantity of the data I was passing. I remember I changed timeouts everywhere but the problem persisted. What I finally did was open the connection as stream request, I needed to change the client and the server side, but it work that way. Since it was a stream connection, the server kept reading until the stream ended.




回答5:


proxy issue can cause this. IIS webconfig put this in

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


来源:https://stackoverflow.com/questions/1215488/system-net-webexception-the-operation-has-timed-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!