Поймать необработанное исключение SocketException во время асинхронного чтения HttpWebResponse

StackOverflow https://stackoverflow.com/questions/1626499

Вопрос

Все асинхронные вызовы HttpWebRequest.BeginGetResponse / EndGetResponse и HttpWebResponse.GetResponseStream (). BeginRead / EndRead сделаны из блоков try / catch, однако эти исключения распространяются и не оставляют шансов обработать их и остановить завершение приложения:

  

Необработанное исключение: System.IO.IOException: невозможно прочитать данные из транспортного соединения: Установленное соединение было прервано программным обеспечением на вашем хост-компьютере. --- > System.Net.Sockets.SocketException: установленное соединение было прервано программным обеспечением на вашем хост-компьютере

     

Необработанное исключение: System.IO.IOException: невозможно прочитать данные из транспортного соединения: Существующее соединение было принудительно закрыто удаленным хостом. --- > System.Net.Sockets.SocketException: существующее соединение было принудительно закрыто удаленным хостом

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)

Фактические фрагменты кода:

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());
    }
}

PS: отчет об ошибке был отправлен в Microsoft Connect на https: / /connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=510564

Это было полезно?

Решение 2

Опубликовано Microsoft 16.11.2009 в 11:14

  

Эта проблема была решена в .NET 4.0 Framework.

     

Спасибо,

     

Команда библиотеки классов сети

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

Другие советы

Я думаю, причина в том, что исключение возникло в потоке, отличном от того, который инициировал BegainGetResponse, и это объясняет вызов System.Threading.ExecutionContext.Run в стеке вызовов.  Может случиться так, что вы выйдете из блока try catch до того, как возникнет исключение, поэтому оно возникает без обработчика, не могли бы вы опубликовать свою часть кода, чтобы я мог увидеть, как мы можем улучшить его

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top