Как прекратить соединение HttpWebRequest в C #? Это не работает, даже установлен тайм-аут или readwritetimeout - PullRequest
8 голосов
/ 19 октября 2011

Я хочу прекратить httpwebrequest, когда соединение занимает слишком много времени.Вот лишь небольшой код, который я написал:

            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 отвечает мне на битовые данные в течение тайм-аута, просто скажем, например, получить 1 байт за 5 секунд, так что время не истекает, но это очень долго.Как я могу разорвать соединение?Спасибо:)

Ответы [ 3 ]

6 голосов
/ 20 октября 2011

Вы можете обнаружить, что тайм-аут на самом деле работает, но поток зависает при попытке закрыть поток.Я не знаю, почему это происходит, но иногда это происходит.Я никогда не использовал ReadToEnd, но я сталкивался с этим при использовании Read.

Я исправил проблему, вызвав Abort в запросе, прежде чем закрыть поток.Это немного круто, но это эффективно.Сокращенный код ниже показывает технику.

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

Я обнаружил, что ReadTimeout и ReadWriteTimeout работают как положено.То есть, когда время чтения истекло, выполнение действительно переходит в блок finally.А если request.Abort нет, звонок на sr.Dispose будет зависать.

2 голосов
/ 20 октября 2011

Прервите чтение потока и прервите, если общее время было слишком длинным.

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();
        }
    }
}
1 голос
/ 30 апреля 2019

Не забудьте также закрыть соединение при исключении.В этом случае объект WebResponse находится в исключении WebException:

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