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);
}
}
}
クライアントは、ATLのサポートを追加して、標準のMFCダイアログベースのプログラムです。マイシンククラス:
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;
}
};
I持って私のダイアログクラスに次のメンバー:のOnInitDialog()で
ITestObjectPtr m_TestObject;
CComObject<CTestObjectEventsSink>* m_TestObjectEventsSink;
DWORD m_Cookie;
:
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