.net COM 交互过程中注意GC的影响

事由是这样的,C#使用了以前的一些COM组件,该COM组件使用多年,Bug相当少见,但是这回经常出现偶见问题。

COM内部有容器类,组件类,容器类释放后,内部组件变为无效。这里出现的故障就是经常出现组件还在,但是容器已被释放的情况。代码如下:

void UseCOM()
{
    IContainer container = GetCOMObject(ContainerGUID);
    IComponent component = container.GetComponent(index);
    component.DoSomthing(); //此处偶见异常
}

经过调试COM代码,明确了是容器组件被释放引起的,但是一直搞不清内中缘由。这段代码在Delphi中使用了好久了。翻译过来就出问题。验证了好久,只能想到一种原因,那就是Delphi中对IContainer接口的引用计数是在函数最后一行才减一的,如果C#中出问题,那么一定是GC提前释放了container引起的。毕竟虽然容器和组件两个对象有内在的关系,可是从GC的角度,两者完全不相关,没有引用关系。只不过GC不一定何时释放容器而已。

这个看法很容易验证,如果将代码稍微修改一下:

void UseCOM()
{
IContainer container = GetCOMObject(ContainerGUID);
IComponent component = container.GetComponent(index);
component.DoSomthing(); //此处偶见异常
Marshal.FinalReleaseComObject(container);
}

那代码就完全没问题了,因为这相当于和Delphi的接口管理范围是一致的了。

之前最佳实践推荐,“对于成员变量,在用完之后要置为Null,而对于局部变量完全没必要,因为GC完全知道这一点”。这更支持了这一观点。最终在<.net 高级调试>中找到了佐证。在Release状态下,一旦对象不再被使用,GC即可回收,而不受变量有效范围的影响。而在Debug模式下,局部变量会一直持续到作用域结束才允许GC回收。

最终,去掉了Marshal一行代码的Debug代码证明了这个理论的正确性。在<MSIL权威指南>一书也有类似概念。感兴趣可以自行查阅。

posted on 2012-04-04 16:25  陈伟强 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/chenwq/archive/2012/04/04/2432049.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值