Catch unhandled SocketException while reading HttpWebResponse asynchronously

All asynchronous calls to HttpWebRequest.BeginGetResponse / EndGetResponse and HttpWebResponse.GetResponseStream (). BeginRead / EndRead are created from try / catch blocks, however these exceptions propagate and leave no chance to handle them and terminate the application:

Unhandled Exception: System.IO.IOException: Unable to read data from transport connection: The established connection was interrupted by your host computer software. ---> System.Net.Sockets.SocketException: The established connection was interrupted by software on your host machine.

Unhandled Exception: System.IO.IOException: Unable to read data from transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

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)

      

Actual code snippets:

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: The bug report was posted to Microsoft Connect https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=510564

+2


source to share


2 answers


Posted by Microsoft on 11/11/2009 11:14 AM

This issue has been fixed in the .NET 4.0 Framework.

Thank,

Network Class Library Command



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

0


source


I think the reason is that the exception was thrown on a different thread than the one that initiated the BegainGetResponse and this explains the call System.Threading.ExecutionContext.Run

on the call stack. It might be that you exit the try catch block before the exception is thrown, so it is raised without a handler, can you post your piece of code so I can see how we can improve it.



0


source







All Articles