3

2 つの ATL COM オブジェクトを持つアウトプロセス COM サーバーがあります。object1 は、内部的に object2 を作成し、次の方法でそれへのインターフェイス ポインターを返すインターフェイスを公開します。

HRESULT CObject1::CreateObject2(IObject2** pIobj2)
{
    CComObject<Object2>* pObj = NULL;

    HRESULT hr = CComObject<Object2>::CreateInstance(&pObj);

    hr = pObj->QueryInterface(IID_IObject2,(void**)pIobj2);

    //Some reason i need to store this pIobj2
    (*pIobj2)->AddRef();

    return hr;
}

Object1 は別のインターフェイスを公開して object2 を削除します

HRESULT CObject1::RemoveObject2(IObject2* pIobj2)
{
    pIobj2->Release(); //This to compensate QI done in CreateObject2

    pIobj2->Release(); //This to compensate addref done to store in create
}

私の要件は、クライアントが のIObject2後のポインターで Release を呼び出さないことIObject1::CreateObject2()です。object2 を破棄するには、を呼び出す必要がIObject1::RemoveObject2()あります。 クライアントを実行すると、 RemoveObject2 の後、 object2 は破棄されませんが、 RemoveObject2 の後にクライアントの Iobject2 ポインターで release を呼び出すと、 object2 が破棄されます。

4

1 に答える 1

2

アウト プロセス COM オブジェクトのライフ サイクル管理は、イン プロセスよりもはるかに複雑です。たとえば、システムは相手が停止する可能性があることを考慮する必要があります (たとえば、クライアント プロセスがリリースなしで停止した場合、サーバーはオブジェクトに割り当てられたリソースをクリーンアップする必要があります)。このため、Microsoft には DCOM ガベージ コレクションがあります。

実際には、クライアント (プロキシ) とサーバー (スタブ) に 2 つの COM オブジェクトがあります。プロキシは独自の参照カウントを維持し、サーバー上のオブジェクト 2 の参照カウントを解放するため、コードはこの参照カウントを混乱させます。この情報はクライアントには届きません。

アーキテクチャを変更することを強くお勧めします。1 つには、オブジェクトを解放する方法は Release メソッドを使用するという COM 契約があります。それがコントラクトであり、設計によって変更されます。これが、DCOM が混乱する理由です。

より良い設計は次のようになると思います:

  1. Object2 で Object1 への参照を保持します (たとえば、m_pobj1)。
  2. Object1::RemoveObject2 はありません。何らかの作業を行う必要がある場合は、代わりにプライベート (非 COM) CleanupObject2 を用意してください。
  3. Object2::FinalRelease (Object2 のクリーンアップ メソッド) を実装し、m_pobj1->Cleanup[Object2(this) を呼び出します。
  4. obj2 へのポインターを obj1 内に保持する必要がある場合は、これらが参照であることを確認してください。つまり、参照カウントを追加せずに、単なるポインターです。

クライアントは Object1::CreateObject2 を呼び出し、obj2 への参照を取得します。それらが完了すると、obj2->Release() が呼び出され、参照カウントがクリアされ、obj1->CleanupObject2 メソッドが呼び出されます。

于 2013-01-19T17:13:58.783 に答える