Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Here is just a simaple code that I wrote:

            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. The situation is after 15minutes I still can get the response but not the full source code of the 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. How can I terminate the connection? Thanks:)

like image 754
Tak Avatar asked Oct 19 '11 04:10

Tak


People also ask

Do you need to close HttpWebRequest?

It is not necessary to call both Stream. Close and HttpWebResponse. Close, but doing so does not cause an error. Failure to close the stream can cause your application to run out of connections.

How do I dispose of HttpWebRequest?

HttpWebRequest does not implement IDisposable so it does not require disposing. just set the httprequest object to null once your done with it.

What is HttpWebRequest C#?

The HttpWebRequest class provides support for the properties and methods defined in WebRequest and for additional properties and methods that enable the user to interact directly with servers using HTTP.


3 Answers

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.

I fixed the problem by calling Abort on the request, before I close the stream. It's a bit of a kluge, but it's effective. 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. That is, when the read times out, execution really does go to the finally block. And if the request.Abort isn't there, the call to sr.Dispose will hang.

like image 74
Jim Mischel Avatar answered Oct 07 '22 07:10

Jim Mischel


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();
        }
    }
}
like image 26
Jon Hanna Avatar answered Oct 07 '22 08:10

Jon Hanna


Make sure to also close the connection on exception. In that case the WebResponse object is on the WebException:

try
{
    using (WebResponse myResponse = request.GetResponse())
      // do stuff
}
catch (WebException webEx)
{
    webEx.Response.Close();
}
like image 24
EM0 Avatar answered Oct 07 '22 07:10

EM0