简体   繁体   English

如何在C#中终止HttpWebRequest连接?它甚至不能设置超时或readwritetimeout

[英]How to terminate HttpWebRequest Connection in C#?It doesn't work even set timeout or readwritetimeout

I want to terminate a httpwebrequest when it takes too long time in connection. 我想在连接时间过长时终止httpwebrequest。 Here is just a simaple code that I wrote: 这是我写的一个simaple代码:

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.Timeout = 5000;
            request.ReadWriteTimeout = 5000;
            request.Proxy = new WebProxy("http://" + proxyUsed + "/", true);
            request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)";

            using (WebResponse myResponse = request.GetResponse())
            {                    
                using (Stream s = myResponse.GetResponseStream())
                {
                    s.ReadTimeout = 5000;
                    s.WriteTimeout = 5000;
                    using (StreamReader sr = new StreamReader(s, System.Text.Encoding.UTF8))
                    {                            
                        result = sr.ReadToEnd();
                        httpLink = myResponse.ResponseUri.AbsoluteUri;
                        sr.Close();
                    }
                    s.Close();
                }
                myResponse.Close();
            }

However, sometimes the connection will take a about 15minutes to get the response. 但是,有时连接需要大约15分钟才能得到响应。 The situation is after 15minutes I still can get the response but not the full source code of the URL. 情况是在15分钟之后我仍然可以获得响应,但不是URL的完整源代码。 I guess that the connection is too slow that the URL response me a bit data within the timeout, just say for example receive 1byte in 5seconds, so it doesn't expire the timoue but it's very long. 我猜这个连接太慢了,以至于URL在超时时间内响应了一些数据,比如说在5秒内接收1byte,所以它不会使timoue到期但是它很长。 How can I terminate the connection? 我该如何终止连接? Thanks:) 谢谢:)

You might find that the timeout is actually working, but the thread hangs when trying to close the stream. 您可能会发现超时实际上正在工作,但在尝试关闭流时线程会挂起。 I don't know why it happens, but sometimes it does. 我不知道它为什么会发生,但有时却会发生。 I've never used ReadToEnd , but I've run across this when using Read . 我从来没有使用过ReadToEnd ,但是在使用Read时我遇到了这个问题。

I fixed the problem by calling Abort on the request, before I close the stream. 我在关闭流之前通过在请求上调用Abort来解决问题。 It's a bit of a kluge, but it's effective. 这有点像kluge,但它很有效。 The abbreviated code below shows the technique. 下面的缩写代码显示了该技术。

HttpWebResponse response = null;
StreamReader sr = null;
try
{
    response = (HttpWebResponse)request.GetResponse(...);
    Stream s = response.GetResponseStream();
    sr = new StreamReader(s, Encoding.UTF8);
    // do your reading here
}
finally
{
    request.Abort();  // !! Yes, abort the request
    if (sr != null)
        sr.Dispose();
    if (response != null)
        response.Close();
}

What I've found is that the ReadTimeout and ReadWriteTimeout work as expected. 我发现ReadTimeoutReadWriteTimeout按预期工作。 That is, when the read times out, execution really does go to the finally block. 也就是说,当读取超时时,执行确实会转到finally块。 And if the request.Abort isn't there, the call to sr.Dispose will hang. 如果request.Abort不存在,则对sr.Dispose的调用将挂起。

Break down the stream reading, and abort if the total time has been too long. 分解流读取,如果总时间太长则中止。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Timeout = 5000;
request.ReadWriteTimeout = 5000;
request.Proxy = new WebProxy("http://" + proxyUsed + "/", true);
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.01; Windows NT 5.0)";//ahem! :)
DateTime giveUp = DateTime.UtcNow.AddSeconds(5); 
using (WebResponse myResponse = request.GetResponse())
{                    
    httpLink = myResponse.ResponseUri.AbsoluteUri;
    using (Stream s = myResponse.GetResponseStream())
    {
        s.ReadTimeout = 5000;
        s.WriteTimeout = 5000;
        char[] buffer = new char[4096];
        StringBuilder sb = new StringBuilder()
        using (StreamReader sr = new StreamReader(s, System.Text.Encoding.UTF8))
        {                            
            for(int read = sr.Read(buffer, 0, 4096); read != 0; read = sr.Read(buffer, 0, 4096))
            {
                if(DateTime.UtcNow > giveUp)
                    throw new TimeoutException();
                sb.Append(buffer, 0, read);
            }
            result = sb.ToString();
        }
    }
}

Make sure to also close the connection on exception. 确保在异常时也关闭连接。 In that case the WebResponse object is on the WebException: 在这种情况下,WebResponse对象位于WebException上:

try
{
    using (WebResponse myResponse = request.GetResponse())
      // do stuff
}
catch (WebException webEx)
{
    webEx.Response.Close();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM