欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

分享我在工作中遇到的多线程下导致RCW无法释放的问题

程序员文章站 2022-04-10 09:59:24
最近有个同事在调用一个类库中的方法时遇到了一个问题,异常信息如下: 尝试释放正在使用的rcw,活动线程或其他线程上正在使用该 rcw,释放正在使用的 rcw 的尝试会...

最近有个同事在调用一个类库中的方法时遇到了一个问题,异常信息如下:

尝试释放正在使用的rcw,活动线程或其他线程上正在使用该 rcw,释放正在使用的 rcw 的尝试会导致损坏或数据丢失。

该方法中对word文件进行相关了操作,因为我之前也在多线程环境下调用过该方法,并且没遇到这个问题,所以同事让我过去看看怎么回事。这个方法在对文件进行相关操作后,会调用另外一个方法释放word对象,部分代码如下:

word._application t = oword as word._application;
object oissave = false;
t.quit(ref oissave, ref omissing, ref omissing);
system.runtime.interopservices.marshal.releasecomobject(odoc);
system.runtime.interopservices.marshal.releasecomobject(oword);
oword = null;
odoc = null;
gc.collect();
gc.collect();

 该段代码是为了保证立即释放word对象并关闭word进程。因为异常信息定位在这里,所以我过去后就从这里开始看,但是看了半天,也没看出类库中的方法有什么问题,因为之前我使用的时候没遇到这种情况,因此我觉得可能不会是这里的问题,并且我负责的那个产品已经经过了大量的测试,肯定是没问题的,所以我说让我看看你是怎么调用的吧,打开他的代码看了一眼,整体上没什么其他问题,但是有个地方引起了我的注意,代码中对该类的实例化放在了全局范围,因为是个cs项目,这么做会导致该对象始终被引用,因此即使在垃圾回收时也无法被释放,而这里调用的又是com组件,就导致了word进程无法关闭,并且同事在这里用的是多线程,所以程序一运行起来,会出现一大堆word进程关不掉。于是就将这里的对象实例化放到了线程方法中,这样在方法执行结束后,堆中的对象就处于无引用状态,在垃圾回收时就被释放了,问题就自然解决了。其实这里跟单线程还是多线程没关系,主要是在全局范围内进行实例化导致了对象不能被垃圾回收,所以在写代码的时候一定要注意对象的生命周期。