C# 在异步HttpWebResponse读取期间捕获未处理的SocketException

C# 在异步HttpWebResponse读取期间捕获未处理的SocketException,c#,asynchronous,httpwebrequest,httpwebresponse,beginreceive,C#,Asynchronous,Httpwebrequest,Httpwebresponse,Beginreceive,对HttpWebRequest.BeginGetResponse/EndGetResponse和HttpWebResponse.GetResponseStream().BeginRead/EndRead的所有异步调用都是从try/catch块进行的,但是,这些异常会传播,不会留下处理它们和停止应用程序终止的机会: 未处理的异常:System.IO.IOException:无法从传输连接读取数据:主机中的软件中止了已建立的连接。-->System.Net.Sockets.SocketExcepti

对HttpWebRequest.BeginGetResponse/EndGetResponse和HttpWebResponse.GetResponseStream().BeginRead/EndRead的所有异步调用都是从try/catch块进行的,但是,这些异常会传播,不会留下处理它们和停止应用程序终止的机会:

未处理的异常:System.IO.IOException:无法从传输连接读取数据:主机中的软件中止了已建立的连接。-->System.Net.Sockets.SocketException:主机中的软件中止了已建立的连接

未处理的异常:System.IO.IOException:无法从传输连接读取数据:远程主机强制关闭了现有连接。-->System.Net.Sockets.SocketException:远程主机强制关闭了现有连接

实际代码片段:

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提交了一份错误报告,我认为原因是引发异常的线程与启动BegaingGetResponse的线程不同,这解释了调用堆栈中的
System.Threading.ExecutionContext.Run
调用。
这种情况可能是您在引发异常之前退出try-catch块,因此它会在没有处理程序的情况下引发,您能否发布您的部分代码,以便我可以看到如何改进它

我认为原因是引发异常的线程与启动BegaingResponse的线程不同,这解释了调用堆栈中的
System.Threading.ExecutionContext.Run
调用。
这种情况可能是,您在引发异常之前退出了try-catch块,因此它会在没有处理程序的情况下引发,您能否发布您的部分代码,以便我可以看到我们如何改进它

Microsoft于2009年11月16日上午11:14发布

此问题已在.NET4.0框架中解决

谢谢,

网络类库小组


微软于2009年11月16日上午11:14发布

此问题已在.NET4.0框架中解决

谢谢,

网络类库小组


我认为您执行BeginGetResponse时缺少了一个部分,我认为这些部分与示例不太相关,但还是包含了一些代码-希望这能更好地解释问题。谢谢我认为您执行BeginGetResponse时缺少了一个部分,我认为这些部分与示例不太相关,但还是包含了一些代码-希望这能更好地解释问题。谢谢那么,对于.net 2开发人员,我应该去visual studio 2010,或者有补丁吗?@Smith,你发现了吗,我也有同样的问题对于.net 2开发人员,我应该去visual studio 2010,或者有补丁吗?@Smith,你发现了吗,我也有同样的问题
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());
    }
}