Pregunta

Todas las llamadas asíncronas a HttpWebRequest.BeginGetResponse / EndGetResponse y HttpWebResponse.GetResponseStream (). BeginRead / EndRead se realizan desde bloques try / catch, sin embargo, estas excepciones se propagan y no dejan una oportunidad para manejarlas y detener la finalización de la aplicación:

  

Excepción no controlada: System.IO.IOException: No se pueden leer los datos de la conexión de transporte: El software de su máquina host anuló una conexión establecida. --- > System.Net.Sockets.SocketException: una conexión establecida fue abortada por el software en su máquina host

     

Excepción no controlada: System.IO.IOException: no se pueden leer los datos de la conexión de transporte: El host remoto cerró a la fuerza una conexión existente. --- > System.Net.Sockets.SocketException: una conexión existente fue cerrada por la fuerza por el host remoto

Unhandled Exception: System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine
   at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.PooledStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.ConnectStream.BeginReadWithoutValidation(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.ConnectStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.IO.Compression.DeflateStream.ReadCallback(IAsyncResult baseStreamResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.ContextAwareResult.CompleteCallback(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Fragmentos de código reales:

public static RequestState StartDownload(string url, string referer, RequestData data, DownloadEventHandler completedHandler, DownloadExceptionHandler failedHandler)
{
    RequestState state = null;

    try
    {
        var request = CreateWebRequest(url, referer, data);
        state = new RequestState(url, data, request)
        {
            DownloadCompleted = completedHandler;
            DownloadFailed = failedHandler;
        }

        state.ResponseAsyncResult = request.BeginGetResponse(WebResponseCallback, state);
        state.AsyncTimeoutHandle = ThreadPool.RegisterWaitForSingleObject(state.CompletedHandle, DownloadTimeoutCallback, state, TimeSpan.FromSeconds(data.DownloadTimeout), true);
    }
    catch(Exception ex)
    {
        Trace.TraceError(ex.ToString());
    }

    return state;
}

private static void DownloadTimeoutCallback(object state, bool timedOut)
{
    var requestState = (RequestState)state;

    try
    {
        requestState.AsyncTimeoutHandle.Unregister(null);

        if(timedOut)
        {
            requestState.Request.Abort();
        }
    }
    catch(Exception ex)
    {
        Trace.TraceError(ex.ToString());
    }
}

private static void WebResponseCallback(IAsyncResult asyncResult)
{
    var state = (RequestState)asyncResult.AsyncState;
    try
    {
        var response = (HttpWebResponse)state.Request.EndGetResponse(asyncResult);
        WebResponse(state, response);
    }
    catch (Exception ex)
    {
        Trace.TraceError(ex.ToString());
    }
}

private static void WebResponse(RequestState state, HttpWebResponse response)
{
    state.ActualUrl = state.Request.Address.ToString();
    state.Response = response;

    BeginRead(state);
}

private static void BeginRead(RequestState state)
{
    var stream = state.Response.GetResponseStream();
    state.ReadAsyncResult = stream.BeginRead(state.Buffer, 0, state.BufferSize, ReadCallBack, state);
}

private static void ReadCallBack(IAsyncResult asyncResult)
{
    var state = (RequestState)asyncResult.AsyncState;

    try
    {
        var stream = state.Response.GetResponseStream();
        var bytesRead = stream.EndRead(asyncResult);

        if (bytesRead > 0)
        {
            //there is still more data to read
            state.AppendResponseData(state.Buffer, 0, bytesRead);
            BeginRead(state);
        }
        else
        {
            state.Response.Close();
            state.InvokeDownloadCompleted();
        }       
    }
    catch(Exception ex)
    {
        Trace.TraceError(ex.ToString());
    }
}

PD: se presentó un informe de error en Microsoft Connect https: / /connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=510564

¿Fue útil?

Solución 2

Publicado por Microsoft el 16/11/2009 a las 11:14 a.m.

  

Este problema se ha resuelto en .NET 4.0 Framework.

     

Gracias,

     

Equipo de biblioteca de clase de red

https://connect.microsoft.com/VisualStudio/feedback /ViewFeedback.aspx?FeedbackID=510564

Otros consejos

Creo que la razón es que la excepción se generó en un subproceso diferente al que inició BegainGetResponse, y esto explica la llamada System.Threading.ExecutionContext.Run en la pila de llamadas.  El caso podría ser que salga del bloque try catch antes de que se genere la excepción, por lo que aumenta sin ningún controlador, ¿puede publicar su parte del código para que pueda ver cómo podemos mejorarlo?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top