2015-05-13 228 views
-1

我有一個自定義接口定義在類型庫中,並在我的代碼中實現。我還沒有創建自己的代理/存根。我已經成功地將我的主線程(STA)的接口指針編組到後臺線程(STA),在我的情況下使用IGlobalInterfaceTable進行異步COM調用 - 是否必須創建自己的P/S?

從該後臺線程中,我想要在UI線程上對該對象進行異步調用。我沒有在我的對象中實現ICallFactory。我看到標準代理確實實現了ICallFactory(即,我可以在ICallFactory的後臺線程上成功執行QI)。但我的自定義界面的CreateCall失敗,HRESULT 0x80040150(無法從註冊表中讀取密鑰)。

我是否需要創建自己的代理,明確實施ICallFactory才能做到這一點?

這裏是我的IDL:

[ 
    object, 
    uuid(92303FE7-A79D-47DD-923F-62062105C00E), 
    async_uuid(2880C40C-9965-4544-AE39-DF08056E8CB6), 
    nonextensible, 
    pointer_default(unique), 
    oleautomation 
] 
interface IFoo: IUnknown 
{ 
    HRESULT Foo([in] long a, [in] long b); 
} 

[ 
    uuid(D58B0A31-A2D5-4BFB-8702-3B710320493B) 
] 
coclass Foo 
{ 
    [default] interface IFoo; 
}; 

下面是在我的單元測試的後臺線程PROC:

static DWORD WINAPI threadproc(LPVOID lpParameter) 
    { 
     // get arguments 
     DWORD cookie = *(DWORD*)lpParameter; 

     // initialize COM 
     Assert::AreEqual(S_OK, CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); 
     { 
      // get global interface table 
      IGlobalInterfaceTablePtr globalInterfaceTable; 
      Assert::AreEqual(S_OK, globalInterfaceTable.CreateInstance(CLSID_StdGlobalInterfaceTable)); 

      // get object 
      MyLib::IFooPtr object; 
      Assert::AreEqual(S_OK, globalInterfaceTable->GetInterfaceFromGlobal(cookie, MyLib::IID_IFoo, (LPVOID*)&object)); 

      // get async call factory 
      ICallFactoryPtr callFactory; 
      Assert::AreEqual(S_OK, object->QueryInterface(&callFactory)); 

      // 
      // Everything is fine up until the CreateCall call below, 
      // which fails with HRESULT 0x80040150 
      // 

      // create async call object 
      IUnknownPtr callObject; 
      Assert::AreEqual(S_OK, callFactory->CreateCall(MyLib::IID_AsyncIFoo, NULL, IID_IUnknown, &callObject)); 
     } 
     // uninitialize COM 
     CoUninitialize(); 

     // success 
     return 0; 
    } 

+0

顯示如何調用'CreateCall'。它失敗了什麼錯誤?另外,您的界面是否有雙重界面(來源於'IDispatch')?從[這篇文檔](https://msdn.microsoft.com/en-us/library/windows/desktop/ms692623.aspx):「** Note **異步支持不適用於'IDispatch'或for繼承'IDispatch'的接口。「 –

+0

我確實看到了該文檔,並採取了相應的措施。但是,我認爲我違反了規則。根據上述文檔,異步內容不適用於IDispatch。所以我的接口只從IUnknown繼承。但是,當接口未標記爲[dual]時,全局接口表的GetInterfaceFromGlobal方法失敗,並且E_FAIL失敗,據我所知它必須從IDispatch繼承。在這一點上,我已經離開了[dual]來完成編組工作,但是卻把IDispatch帶出來,希望能夠使異步調用成爲可能。 –

+0

另外:增加了錯誤的詳細信息 –

回答

0

據我所知,通用編組不與異步工作COM。您需要構建(MIDL生成的)代理(儘管,IIRC,如果您正在構建DLL,則可以合併存根)。

您還需要註冊代理DLL(並使用-DREGISTER_PROXY_DLL定義構建它)。異步COM需要定義更多的註冊表項才能使其工作。

相關問題