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

时间:2011-10-19 04:08:41

标签: c# httpwebrequest timeout

我希望在连接时间过长时终止httpwebrequest。 这是我写的一个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();
            }

但是,有时连接需要大约15分钟才能得到响应。 情况是在15分钟之后我仍然可以获得响应,但不是URL的完整源代码。 我猜这个连接太慢了,以至于URL在超时时间内响应了一些数据,比如说在5秒内接收1byte,所以它不会使timoue到期但是它很长。 我该如何终止连接? 感谢:)

3 个答案:

答案 0 :(得分:6)

您可能会发现超时实际上正在运行,但在尝试关闭流时线程会挂起。我不知道它为什么会发生,但有时却会发生。我从未使用ReadToEnd,但在使用Read时遇到过这种情况。

我在关闭流之前通过在请求上调用Abort来解决问题。这有点像kluge,但它很有效。下面的缩写代码显示了该技术。

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

我发现ReadTimeoutReadWriteTimeout按预期工作。也就是说,当读取超时时,执行确实会转到finally块。如果request.Abort不存在,则对sr.Dispose的调用将会挂起。

答案 1 :(得分:2)

分解流读数,如果总时间太长则中止。

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

答案 2 :(得分:1)

确保在异常时也关闭连接。在这种情况下,WebResponse对象位于WebException上:

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