2015-01-02 3 views
5

Область.NET HTTP Request Timeout не «Aborting» на постоянном месте потокового

Я разработал обертку для Http Web Request класса для выполнения получает и сообщения в более простом способе. Эта библиотека используется без каких-либо проблем уже более двух лет, но сегодня мы столкнулись с какой-то странной проблемой.

one website (это займет некоторое время, чтобы загрузить), что, по-видимому, сохраняет потоковые символы в интерфейсе HTML, поэтому наша библиотека «Получить» запрос застревает в цикле.

Различные свойства таймаута

Глядя на ссылки веб-запроса Http мы видим, что есть два различных timeout свойства. Мы используем их оба, но ни один из них, похоже, не подходит должным образом.

  • Read Write Timeout - Получает или задает тайм-аут в миллисекундах при записи или чтении из потока.
  • Timeout - Получает или задает значение тайм-аута в миллисекундах для методов GetResponse и GetRequestStream.

Один тайм-аут, чтобы управлять ими всеми

Есть ли способ, чтобы установить операцию «Тайм-аут», что заставит поток/соединение, располагающее после некоторого заранее заданного времени?

Некоторые Пример кода

public class Program 
{ 
public static void Main() 
{ 
    string url = "http://anus.io"; 

    Console.WriteLine("Initializing Request State Object"); 

    RequestState myRequestState = new RequestState(); 

    // Creating Http Request 
    myRequestState.request = (HttpWebRequest)WebRequest.Create(url); 
    myRequestState.request.Method   = "GET"; 
    myRequestState.request.ReadWriteTimeout = 4000; 
    myRequestState.request.Timeout   = 4000; 

    Console.WriteLine("Begining Async Request"); 


    IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState); 

    Console.WriteLine("Waiting for Results"); 
    ar.AsyncWaitHandle.WaitOne(); 

    myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar); 
    Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode); 

} 

public static void ResponseCallback (IAsyncResult asyncResult) 
{ 
    Console.WriteLine("Completed"); 
} 
} 

This Code seem to work fine, но как я прочитал ответ в виде строки, так как она постоянно Передано (как браузер показывает)?

Вопрос

Что такое правильный способ справиться с веб-сайтов, как это? (Под ручкой я имею в виду, чтобы быть в состоянии идентифицировать и пропустить ситуации, когда сервер просто не остановить передачу?)

ответ

1

Попробуйте это:

public static void Main() 
{ 

    string url = "http://anus.io"; 

    ***int DefaultTimeOut = 15000;*** //timeout after 15 sec 

    Console.WriteLine("Initializing Request State Object"); 

    RequestState myRequestState = new RequestState(); 

    // Creating Http Request 
    myRequestState.request = (HttpWebRequest)WebRequest.Create(url); 
    myRequestState.request.Method   = "GET"; 
    myRequestState.request.ReadWriteTimeout = 4000; 
    myRequestState.request.Timeout   = 4000; 

    Console.WriteLine("Begining Async Request"); 


    IAsyncResult ar = myRequestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), myRequestState); 

    ***ThreadPool.RegisterWaitForSingleObject(ar.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myRequestState.request, DefaultTimeOut, true);*** 

    Console.WriteLine("Waiting for Results"); 
    ar.AsyncWaitHandle.WaitOne(); 

    try{ 

    myRequestState.response = (HttpWebResponse)myRequestState.request.EndGetResponse(ar); 
    Console.WriteLine("Response status code = {0}", myRequestState.response.StatusCode); 
    }catch(Exception){ 
     Console.WriteLine("Request Aborted"); 
    } 
} 

public static void ResponseCallback (IAsyncResult asyncResult) 
{ 
    Console.WriteLine("Completed"); 
} 

//call the timeout if more than 15 seconds 

**public static void TimeoutCallback(object state, bool timedOut) 
{ 
      if (timedOut) 
      { 
       HttpWebRequest request = state as HttpWebRequest; 
       if (request != null) 
       { 
        request.Abort(); 
       } 
      } 
}** 
0

Я бы переместить всю обработку HTTP в Task и использования общий метод, чтобы поставить тайм-аут на эту задачу. Многие такие методы доступны.

Я не понимаю, почему вам нужно столько индивидуальных тайм-аутов. Разве вы не можете просто сказать: если этот запрос занимает больше 4 секунд, независимо от причины, убейте его.

Шаблон APM и ожидание событий - это красные флаги в эпоху .NET 4.5 и C# 5. Все это нежелание скрывает намерение вашего кода. Хлам уходит, если вы используете await для использования async IO, предоставленного классом WebRequest, и используйте обходную технику таймаута.