COM对象无意中被释放

时间:2016-03-04 14:54:58

标签: c# static com arcobjects

我的单元测试有一个帮助类,它共享对内存中COM对象的引用:

public class UnitTestGeometryProvider 
{
    public static readonly IGeometry Geometry = Deserialize();
}

从Xml文件反序列化几何体,该文件存储为资源文件并附加到项目中。然后它被包装到COM对象中:

public static IGeometry Deserialize() 
{
    return (IGeometry) new XMLSerializerClass().LoadFromString(myXDoc.OuterXml, null, null);
}

现在我有两个使用此类中存储的几何的测试方法:

[TestClass()]
public class MyTest
{
    [TestMethod()]
    public void FirstTest()
    {
        var p = UnitTestGeometryProvider.Geometry;
    }   

    [TestMethod()]
    public void SecondTest()
    {
        var p = UnitTestGeometryProvider.Geometry;
    }
}

当运行第二个时,我得到一个COMException:

  

无法使用已与其基础RCW分离的COM对象

我想知道为什么COM-object的引用在static中标记为UnitTestGeometryProvider时被释放,我没有明确地释放它。所以即使如果 托管资源到实例将超出范围(这不是静态),底层COM对象应该只在我所有的时候消失当应用程序终止时,测试是否已完成或更通用,或者我是否遗漏了任何内容?

我正在使用ArcObjects和Visual NUnit。

1 个答案:

答案 0 :(得分:0)

由于Hans Passant的评论,我发现了实际问题。

显然,Visual-NUnit-Framework决定为每个测试创建一个单独的线程。因此,每当我创建一个COM对象 - 无论是静态还是非 - 时,该对象都存在于这个单独的线程中,不能在另一个线程中使用。如果线程死也会执行COM对象或更准确地引用它。这导致GC开始抛弃COM对象,因为在该线程不存在对它的管理引用。

解决方案非常简单:我将静态字段更改为instance-members,并在我的测试类中创建了类型为UnitTestGeometryProvider的实例成员。因此,每个测试都会生成一个新的提供者 然而,这个解决方案非常烦人,因为必须初始化Geometry - 属性,因此Deserialize - 方法为每个测试运行,而不是仅对所有测试运行一次。

我不知道是否存在一个线程安全的解决方案,当初始化它的第一个线程死亡时,不会终止对COM对象的引用。