简体   繁体   English

COM对象意外释放

[英]COM-object was released unintendedly

I have a helper-class for my unit-tests that share a reference to an COM-object in memory: 我的单元测试有一个帮助程序类,该类共享对内存中COM对象的引用:

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

The geometry is deserialized from a Xml file which is stored as a resource file and appended to the project. 从Xml文件反序列化几何图形,该文件存储为资源文件并附加到项目中。 Afterwards it is wrapped into a COM object: 然后将其包装到COM对象中:

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

Now I have two test-methods that use the geometry stored within this class: 现在,我有两个使用存储在此类中的几何的测试方法:

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

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

When running the second one I get a COMException: 运行第二个时,我得到一个COMException:

COM object that has been separated from its underlying RCW cannot be used 与它的基础RCW分开的COM对象不能使用

I wonder why the reference to the COM-object is released as it is marked static in UnitTestGeometryProvider and I do not explicitly release it. 我不知道为什么要释放对COM对象的引用,因为它在UnitTestGeometryProvider标记为static ,而我没有明确释放它。 So even if the managed resource to the instance would go out of scope (which is does not at it is static), the underlying COM object should go away only when all my tests finished or more general when the application terminates, or do I miss anything? 所以,即使 托管资源的实例将走出去的范围(这是不它是静态的),下面的COM对象应该走在应用程序终止,只有当所有我的测试成品或更一般的,还是我错过有什么事吗

I am using ArcObjects and Visual NUnit. 我正在使用ArcObjects和Visual NUnit。

Due to the comments by Hans Passant I found the actual problem. 由于Hans Passant的评论,我发现了实际的问题。

Obviously the Visual-NUnit-Framework decides to create a separate thread for every test. 显然,Visual-NUnit-Framework决定为每个测试创建一个单独的线程。 Thus whenever I create a COM-object - be it static or not - this object lives on this single thread and cannot be used in another one. 因此,无论何时创建COM对象(无论是否为静态对象),该对象都位于该单个线程上,并且不能在另一个线程中使用。 If the thread dies also does the COM-object or to be more precise the reference to it. 如果线程死亡,也执行COM对象,或者更确切地说,引用该对象。 This leads to the GC kicking in throwing the COM-object away as no more managed references to it exist within that thread . 这导致GC开始抛出COM对象,因为该线程中不再存在对其的托管引用。

The solution is pretty straitforward: I changed the static field to instance-members and created an instance-member of type UnitTestGeometryProvider within my test-class. 解决方案非常棘手:我将静态字段更改为实例成员,并在测试类中创建了UnitTestGeometryProvider类型的实例成员。 Thus a new provider is generated by every test. 因此,每次测试都会生成一个新的提供程序。
However this solution is quite annoying because the Geometry -property has to be initialized and therefor the Deserialize -method runs for every test instead of only once for all tests. 但是,此解决方案非常烦人,因为必须初始化Geometry属性,并且因此对每个测试运行Deserialize方法,而不是对所有测试仅运行一次。

I don´t know if there is a thread-safe solution to not kill the reference to the COM-object when the first thread that intialized it dies. 我不知道是否有一个线程安全的解决方案来在初始化它的第一个线程死亡时不终止对COM对象的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM