异步webrequest超时=>崩溃IIS

时间:2012-05-30 14:23:44

标签: c# .net-4.0 asynchronous webrequest

我有一个网络应用,可以从外部服务获取数据。请求本身就像下面的代码一样 - 就我所见,非常简单。创建一个请求,异步激活它并让回调处理响应。在我的开发环境中正常工作。

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以同步执行请求,效果很好。该请求在这些环境中仍然超时,但没有造成任何损害,应用程序将继续幸运地运行。

所以我有点解决了我的问题,但为什么会这样呢?任何人都可以开导我吗? : - )

1 个答案:

答案 0 :(得分: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
    }
});

您的异常处理程序仅涵盖任务的创建 - 而不是回调。