2012-05-30 52 views
6

我有一个web应用程序,它从外部服务获取数据。请求本身就像下面的代码一样发生 - 就我所能看到的而言非常简单。创建一个请求,将其异步激活并让回调处理响应。适用于我的开发环境。异步webrequest超时=>崩溃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: 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) 

..所以这一切归结为一个SocketException,在我看来。和右后另一个事件(我猜是相关的)(在同一秒内)记录:

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

这有点超出了我,我没有异步代码和线程的主人,但来自Web请求的超时导致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

嗯,所以解释就是这么简单。似乎马上做这个伎俩。非常感谢!现在,如何让这些浪费时间回来... –