2012-05-30 3 views
6

У меня есть веб-приложение, которое получает данные от внешних служб. Сам запрос происходит, как в приведенном ниже кодексе, - насколько я понимаю. Создайте запрос, запустите его асинхронно и позвольте обратному сообщению обрабатывать ответ. Хорошо работает в моей среде.Async webrequest times out => Сбой IIS

public static void MakeRequest(Uri uri, Action<Stream> responseCallback) 
     { 
      WebRequest request = WebRequest.Create(uri); 
      request.Proxy = null; 
      request.Timeout = 8000; 
      try 
      { 
       Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null) 
        .ContinueWith(task => 
             { 
              WebResponse response = task.Result; 
              Stream responseStream = response.GetResponseStream(); 
              responseCallback(response.GetResponseStream()); 
              responseStream.Close(); 
              response.Close(); 
             }); 
      } catch (Exception ex) 
      { 
       _log.Error("MakeRequest to " + uri + " went wrong.", ex); 
      } 
     } 

Однако внешние условия тестирования и производственная среда по причинам, не зависящим от меня, не достигают целевого URL. Хорошо, подумал я, - тайм-аут запроса никому не повредит. Однако казалось, что каждый раз, когда этот запрос прерывался, ASP.NET разбился, и IIS был перезапущен. Журнал событий показывает мне, между прочим, этот StackTrace:

StackTrace: at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 
    at System.Threading.Tasks.Task`1.get_Result() 
    at MyApp.AsyncWebClient.<>c__DisplayClass2.<MakeRequest>b__0(Task`1 task) 
    at System.Threading.Tasks.Task`1.<>c__DisplayClass17.<ContinueWith>b__16(Object obj) 
    at System.Threading.Tasks.Task.InnerInvoke() 
    at System.Threading.Tasks.Task.Execute() 

InnerException: System.Net.WebException 

Message: Unable to connect to the remote server 

StackTrace: at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) 
    at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs) 

InnerException: System.Net.Sockets.SocketException 

Message: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 

StackTrace: at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) 
    at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception) 

..so Это все сводится к SocketException, мне кажется. И сразу после этого (в пределах того же секунда) другое события (которое я предполагаю, что это уместно) регистрируются:

Exception Info: System.AggregateException 
Stack: 
    at System.Threading.Tasks.TaskExceptionHolder.Finalize() 

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

Итак, я решил решить свою проблему, но почему это происходит? Может ли кто-нибудь просветить меня? :-)

ответ

12

Ваше продолжение должно быть связано с тем, что .Result может отражать исключение. В противном случае у вас есть необработанное исключение. Необработанные исключения убивают процессы.

.ContinueWith(task => 
{ 
    try { 
     WebResponse response = task.Result; 
     Stream responseStream = response.GetResponseStream(); 
     responseCallback(responseStream); 
     responseStream.Close(); 
     response.Close(); 
    } catch(Exception ex) { 
     // TODO: log ex, etc 
    } 
}); 

ваш старый обработчик исключений охватывает только создание задачи - не обратного вызова.

+0

А, так объяснение простое. Казалось, что делать трюк сразу. Большое спасибо! Теперь, как получить те потраченные впустую часы назад ... –