Ho un'app Web che riceve dati da servizi esterni. La richiesta stessa avviene come il seguente codice - abbastanza semplice per quanto posso vedere. Crea una richiesta, sparagli via in modo asincrono e lascia che il callback gestisca la risposta. Funziona benissimo sul mio ambiente di sviluppo.Timeout richiesta asincrona => Arresti anomali 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);
}
}
Tuttavia ambienti di test esterni e l'ambiente di produzione potrebbe, per ragioni indipendenti me, non raggiungono l'URL di destinazione. Bene, ho pensato - un timeout della richiesta non farà davvero male a nessuno. Tuttavia, sembrava che ogni volta che questa richiesta fosse scaduta, ASP.NET si arrestava in modo anomalo e IIS veniva riavviato. Il registro eventi mi mostra, tra le altre cose, questo 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)
..quindi tutto si riduce ad una SocketException, mi pare. E subito dopo (all'interno dello stesso secondo) un altro evento (che sto cercando di indovinare che è rilevante) si registra:
Exception Info: System.AggregateException
Stack:
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
Questa è una sorta di là di me, come io non sono padrone di codice asincrono e filettatura, ma che un timeout da una richiesta web causa il crash di IIS sembra molto strano. Ho reimplementato MakeRequest
per eseguire le richieste in modo sincrono, il che funziona alla grande. La richiesta è ancora scaduta in quegli ambienti, ma nessun danno è stato fatto e l'app continua a funzionare felicemente per sempre.
Quindi ho risolto il problema, ma perché succede? Qualcuno può illuminarmi? :-)
Ah, quindi la spiegazione è così semplice. Sembrava fare il trucco immediatamente. Grande grazie! Ora, come ottenere indietro quelle ore sprecate ... –