我有一個用C#編寫的託管COM對象和一個用C++(MFC和ATL)編寫的本地COM客戶端和接收器。客戶端創建該對象並在啓動時向其事件接口提供建議,並從其事件接口取消並在關閉時釋放該對象。問題在於COM對象有一個對接收器的引用,它在垃圾收集運行之前不會被釋放,此時客戶端已被拆除,因此通常會導致訪問衝突。這可能不是什麼大事,因爲客戶正在關閉,但我希望儘可能優雅地解決這個問題。我需要我的COM對象以更及時的方式釋放我的接收器對象,並且我不知道從哪裏開始,因爲我的COM對象不能明確地與接收器對象一起工作。如何在使用COM互操作時管理對象生命週期?
我的COM對象:
public delegate void TestEventDelegate(int i);
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITestObject
{
int TestMethod();
void InvokeTestEvent();
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITestObjectEvents
{
void TestEvent(int i);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ITestObjectEvents))]
public class TestObject : ITestObject
{
public event TestEventDelegate TestEvent;
public TestObject() { }
public int TestMethod()
{
return 42;
}
public void InvokeTestEvent()
{
if (TestEvent != null)
{
TestEvent(42);
}
}
}
客戶端是一個標準的基於對話框的MFC程序,與ATL額外的支持。我的接收器類:
class CTestObjectEventsSink : public CComObjectRootEx<CComSingleThreadModel>, public ITestObjectEvents
{
public:
BEGIN_COM_MAP(CTestObjectEventsSink)
COM_INTERFACE_ENTRY_IID(__uuidof(ITestObjectEvents), ITestObjectEvents)
END_COM_MAP()
HRESULT __stdcall raw_TestEvent(long i)
{
return S_OK;
}
};
我在我的對話框類以下成員:
ITestObjectPtr m_TestObject;
CComObject<CTestObjectEventsSink>* m_TestObjectEventsSink;
DWORD m_Cookie;
在OnInitDialog():
HRESULT hr = m_TestObject.CreateInstance(__uuidof(TestObject));
if(m_TestObject)
{
hr = CComObject<CTestObjectEventsSink>::CreateInstance(&m_TestObjectEventsSink);
if(SUCCEEDED(hr))
{
m_TestObjectEventsSink->AddRef(); // CComObject::CreateInstace() gives an object with a ref count of 0
hr = AtlAdvise(m_TestObject, m_TestObjectEventsSink, __uuidof(ITestObjectEvents), &m_Cookie);
}
}
在的OnDestroy():
if(m_TestObject)
{
HRESULT hr = AtlUnadvise(m_TestObject, __uuidof(ITestObjectEvents), m_Cookie);
m_Cookie = 0;
m_TestObjectEventsSink->Release();
m_TestObjectEventsSink = NULL;
m_TestObject.Release();
}
在我看來,你忘記了m_TestObjectEventsSink-> Release()。它不是自動的,因爲你存儲了一個指向CComObject <>的指針,你可能只是在泄漏它。不知道爲什麼這是必要的。 –
哎呀,對不起。忘了這些,但效果是一樣的CComObject :: CreateInstance()爲您提供ref對象爲0.我會更新問題,無論。 – Luke
CComObject :: CreateInstance()爲您提供ref對象爲0的對象;這是你的責任AddRef()它。 – Luke