【发布时间】:2011-06-29 20:04:15
【问题描述】:
这是我没有按预期顺序清理的代码的简化版本。此示例代码在退出时导致访问冲突,因为正在包装的本机对象在取消订阅之前已被删除。
场景是 C# 客户端正在创建两个具体的 CLI 对象并将它们存储为接口句柄。然后设置一个具体对象来存储对另一个对象的引用,同样通过接口句柄。建立这种关系是为了提供围绕两个类的托管包装器,其中一个在本机级别订阅另一个。
我希望例如对象 A 持有对对象 B 的引用会阻止对象 B 被最终确定/处置?这不是我观察到的。有没有更好的方法来表示关系以便清理正确?
原生类:
#pragma managed(push, off)
class CNative2;
//------------------------------------------------------------------------------
class CNative1
{
public:
CNative1(){}
~CNative1(){}
void Subscribe( CNative2* pn2 )
{
m_pn2 = pn2;
}
void Unsubscribe()
{
m_pn2 = 0;
}
CNative2* m_pn2;
};
//------------------------------------------------------------------------------
class CNative2
{
public:
CNative2(){}
~CNative2()
{
m_pn1->Unsubscribe();
}
void Initialize( CNative1* pn1 )
{
m_pn1 = pn1;
m_pn1->Subscribe( this );
}
private:
CNative1* m_pn1;
};
#pragma managed(pop)
CLI 类库代码:
#include "Native.h"
using namespace System;
namespace CLILib
{
//------------------------------------------------------------------------------
public interface class Interface1
{
};
//------------------------------------------------------------------------------
public interface class Interface2
{
void Initialize( Interface1^ i1 );
};
//------------------------------------------------------------------------------
public ref class Class1 : Interface1
{
public:
Class1()
{
m_pn1 = new CNative1();
};
~Class1()
{
this->!Class1();
}
!Class1()
{
delete m_pn1;
}
internal:
CNative1* GetNative()
{
return m_pn1;
}
private:
CNative1* m_pn1;
};
//------------------------------------------------------------------------------
public ref class Class2 : Interface2
{
public:
Class2()
{
m_pn2 = new CNative2();
}
~Class2()
{
this->!Class2();
}
!Class2()
{
delete m_pn2;
}
virtual void Initialize( Interface1^ i1 )
{
m_i1 = i1;
Class1^ c1 = safe_cast< Class1^ >( i1 );
m_pn2->Initialize( c1->GetNative() );
}
Interface1^ m_i1;
private:
CNative2* m_pn2;
};
}
C# 客户端代码:
using CLILib;
namespace ManagedClient
{
class Program
{
static void Main( string[] args )
{
for ( int i = 0; i < 1000000; ++i )
{
Interface1 i1 = new Class1();
Interface2 i2 = new Class2();
i2.Initialize( i1 );
}
}
}
}
【问题讨论】:
标签: interface reference garbage-collection c++-cli handle