对异步使用的 HttpWebRequest 调用 Abort 时出现 ObjectDisposeException

发布于 2024-10-07 04:00:54 字数 3930 浏览 4 评论 0原文

正如标题所示,在异步使用的 HttpWebRequest 上调用 "Abort" 时,我似乎收到了 ObjectDisposeException (即 BeginGetResponse< /code>) 并且无法,对于我的一生来说,弄清楚如何防止它。我花了一整天的时间寻找解决方案,因此我们将不胜感激。这是一个说明问题的简单示例:

// helper class that gets passed through as the state
class RequestState
{
    public HttpWebRequest Request { get; set; }
    public bool TimedOut { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var rs = new RequestState
        {
            Request = (HttpWebRequest)WebRequest.Create("http://google.com")
        };

        var result = rs.Request.BeginGetResponse(
            asyncResult =>
            {
                if (asyncResult.IsCompleted)
                {
                    var reqState = asyncResult.AsyncState as RequestState;

                    if (reqState != null && !reqState.TimedOut)
                    {
                        using (var response = reqState.Request.EndGetResponse(asyncResult) as HttpWebResponse)
                        {
                            using (var streamReader = new StreamReader(response.GetResponseStream()))
                            {
                                Console.WriteLine(streamReader.ReadToEnd());
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("Timed out!");
                    }
                }
            },
            rs);

        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
            (state, timeout) =>
            {
                if (timeout)
                {
                    var temprs = state as RequestState;
                    if (temprs != null)
                    {
                        // set TimedOut flag
                        temprs.TimedOut = true;
                        // this will cause the BeginGetResponse callback above to be called
                        temprs.Request.Abort();
                    }
                    // after this method leaves scope the ObjectDisposedException occurs!
                }
            },
            // time out of 7 seconds
            rs, 7000, true);

        Console.ReadLine();


    }
}

这是我正在做的事情: 如果我正常运行它,响应就会很好地写入控制台。但是,如果我使用 Fiddler 模拟缓慢的互联网连接(或基本上没有连接)并且执行超时回调,我会得到前面提到的 ObjectDisposeException"Timed out!" 是不过首先写入控制台)。如果我不对 HttpWebRequest 调用 Abort,则不会出现此异常。

谁能告诉我我做错了什么?我的目标是 .NET 3.5 框架。预先感谢您的任何启发。

这是异常信息/调用堆栈:

System.ObjectDisposedException occurred
    Message=Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
    Source=System
    ObjectName=System.Net.Sockets.NetworkStream
    StackTrace:
        at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
    InnerException: 

System.Net.Sockets.NetworkStream.EndRead(System.IAsyncResult asyncResult) + 0x1b7 bytes 
System.Net.PooledStream.EndRead(System.IAsyncResult asyncResult) + 0x10 bytes   
System.Net.Connection.ReadCallback(System.IAsyncResult asyncResult) + 0x33 bytes    
System.Net.Connection.ReadCallbackWrapper(System.IAsyncResult asyncResult) + 0x46 bytes 
System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) + 0x69 bytes   
System.Net.ContextAwareResult.Complete(System.IntPtr userToken) + 0xab bytes    
System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken) + 0xb0 bytes 
System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0x94 bytes    
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x54 bytes

As the title indicates, I seem to be getting an ObjectDisposedException when calling "Abort" on an HttpWebRequest used asynchronously (i.e. BeginGetResponse) and can't, for the life of me, figure out how to prevent it. I have spent all day searching for a solution so any help would be appreciated. Here is a simple example illustrating the problem:

// helper class that gets passed through as the state
class RequestState
{
    public HttpWebRequest Request { get; set; }
    public bool TimedOut { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var rs = new RequestState
        {
            Request = (HttpWebRequest)WebRequest.Create("http://google.com")
        };

        var result = rs.Request.BeginGetResponse(
            asyncResult =>
            {
                if (asyncResult.IsCompleted)
                {
                    var reqState = asyncResult.AsyncState as RequestState;

                    if (reqState != null && !reqState.TimedOut)
                    {
                        using (var response = reqState.Request.EndGetResponse(asyncResult) as HttpWebResponse)
                        {
                            using (var streamReader = new StreamReader(response.GetResponseStream()))
                            {
                                Console.WriteLine(streamReader.ReadToEnd());
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("Timed out!");
                    }
                }
            },
            rs);

        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle,
            (state, timeout) =>
            {
                if (timeout)
                {
                    var temprs = state as RequestState;
                    if (temprs != null)
                    {
                        // set TimedOut flag
                        temprs.TimedOut = true;
                        // this will cause the BeginGetResponse callback above to be called
                        temprs.Request.Abort();
                    }
                    // after this method leaves scope the ObjectDisposedException occurs!
                }
            },
            // time out of 7 seconds
            rs, 7000, true);

        Console.ReadLine();


    }
}

Here is what I am doing:
If I run this normally, the response is written to the console just fine. However, if I use Fiddler to simulate a slow internet connection (or basically no connection) and the timeout callback executes, I get the aforementioned ObjectDisposedException ("Timed out!" is written to the console first though). I do not get this exception if I do not call Abort on the HttpWebRequest.

Can anyone tell me what I am doing wrong? I am targeting the .NET 3.5 framework. Thank you in advance for any enlightenment.

Here is the exception info/call stack:

System.ObjectDisposedException occurred
    Message=Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
    Source=System
    ObjectName=System.Net.Sockets.NetworkStream
    StackTrace:
        at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
    InnerException: 

System.Net.Sockets.NetworkStream.EndRead(System.IAsyncResult asyncResult) + 0x1b7 bytes 
System.Net.PooledStream.EndRead(System.IAsyncResult asyncResult) + 0x10 bytes   
System.Net.Connection.ReadCallback(System.IAsyncResult asyncResult) + 0x33 bytes    
System.Net.Connection.ReadCallbackWrapper(System.IAsyncResult asyncResult) + 0x46 bytes 
System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) + 0x69 bytes   
System.Net.ContextAwareResult.Complete(System.IntPtr userToken) + 0xab bytes    
System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken) + 0xb0 bytes 
System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0x94 bytes    
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x54 bytes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文