[AsyncHandle]什么引发了ObjectDisposedException?

Version

Date

Creator

Description

1.0.0 .1

2006-9-19

郑昀

草稿

 

继续阅读之前,我们假设您熟悉以下知识:

n         IDisposable 接口释放 dotNET 资源

如果不熟悉这些知识点,可以看本文最后资源列表中的文章。

本文讨论了出现不可捕获的 ObjectDisposedException 异常崩溃,寻找可能的原因,并试图解决

[ 现象 ]

关键词       ObjectDisposedException

表象           我的 dotNET C# 服务偶尔会彻底崩溃,时机没有规律可循,崩溃时在 Windows 事件日志中有来自于“ .NET Runtime 2.0 Error Reporting ”的报告,描述的错误也颇让人费思量。

错误描述          

事件类型 :     错误

事件来源 :     .NET Runtime 2.0 Error Reporting

事件种类 :    

事件 ID:       5000

描述 :

EventType clr20r3, P1 juiceextractor.exe, P2 1.0.0.0, P3 450d5160, P4 mscorlib, P5 2.0.0.0, P6 4333ab80, P7 10ed, P8 0, P9 system.objectdisposedexception , P10 NIL.

 

通过 ObjectDisposedException 对我们的提醒,可以了解到这是因为前面已经使用了一个 disposed 对象。在一个使用过 disposed 对象上调用其他方法时是会引发致命异常的,服务也不知道该在哪里捕获这个异常,似乎也不可捕获。但是,问题是,是谁引发的?

 

引申           看到微软的一个对 dotnet framework servicepack 公告中提到:当一个异步 Web 请求在接收到响应之前如果被中止,则会引发 ObjectDisposedException

 

唯一和异步请求有点关系的是,本服务向一个 socket 服务器发送请求,并等候一段一段地循环接收服务器的大量数据反馈。这中间,使用了 C# 的异步方法 BeginReceive 来告知 socket 如何接收数据。

这个逻辑的代码如下:

C# code

/// <summary>

/// 调用异步方法 BeginReceive 来告知 socket 如何接收数据

/// </summary>

IAsyncResult ar =

_socket.BeginReceive(_recvBuffer.Buffer, 0, _recvBuffer.Buffer.Length,

                SocketFlags.None, _recvCallback, _socket);

 

// 设定一个期限, 10 分钟内如果还没有结果返回,

// 我们可以认为必须关掉当前 socket 连接了,不要再等了 !

ar.AsyncWaitHandle.WaitOne(new TimeSpan(0, 10, 0), true);

ar.AsyncWaitHandle.Close();

….

public void RecvCallback(IAsyncResult result)

{…

 

也就是利用回调函数 _recvCallback ”,每次有数据的话,都直接调用它。但是,规定了如果 10 分钟内都没有完整结果返回,那么这个异步等候句柄将被关闭。

 

很简单的想法。

但是如果数据量大的话, socket 服务器计算的过程非常漫长,导致返回数据的过程超过了 10 分钟,会发生什么事情呢?

[ 回答前面的问题 ]

这个时候,“ ar.AsyncWaitHandle.Close(); ”是不是就导致了 ObjectDisposedException 呢?

假设如此的话。

第一,那我们需要调用 AsyncWaitHandle.Close() 这句话吗?

The Thread Pool and Asynchronous Methods 中说道:“ Note the call to ar.AsyncWaitHandle.Close() . This prevents the WaitHandle leaking until garbage collection. The leak wouldn't cause any problems in most cases (unlike, for instance, file handles leaking), but in situations where FireAndForget would be called many, many times in quick succession, you could end up with a vast number of handles until the garbage collector started finalizing them. (This is also a bad thing in terms of performance - you shouldn't leave things to be finalised when it can be avoided.)

那么,也许我们可以不调用它,来规避 ObjectDisposedException 异常崩溃?

 

第二,把 ar.AsyncWaitHandle.WaitOne(new TimeSpan(0, 10, 0), true); 等候的时间延长?比如说延长到 40 分钟。这样也可以避免 ObjectDisposedException

[ 改变接收模式 ]

第三,对于这种长时间执行的 socket 服务器,可以不用在一个端口上干等,可以发送请求用一个端口,接收数据反馈用另外一个 socket 端口号。

以前没有考虑到计算时间如此之长,所以才做成了 socket 异步接收模式。后来算法作了改变,有时候十分钟的等候都不够了。

  [ 参考资料 ]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值