2015-05-13 2 views
-1

У меня есть пользовательский интерфейс, определенный в библиотеке типов и реализованный в моем коде. Я не создал свой собственный прокси-сервер. Я успешно обработал указатель интерфейса из основного потока (STA) в фоновый поток (STA), в моем случае используя IGlobalInterfaceTable.Выполнение вызова async COM - нужно ли мне создавать собственные P/S?

Из этой фоновой темы я хочу сделать асинхронный вызов объекта в потоке пользовательского интерфейса. Я не реализовал ICallFactory в моем объекте. Я вижу, что стандартный прокси действительно реализует ICallFactory (т. Е. Я могу успешно выполнить QI в фоновом потоке для ICallFactory). Но 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; 
}; 

А вот фон нить прок в моем тестовом модуле:

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): «** Примечание ** Асинхронная поддержка недоступна для' IDispatch' или для интерфейсы, наследующие 'IDispatch'. –

+0

Я видел эту документацию и действовал соответствующим образом. Однако, я думаю, что нарушаю правила. В соответствии с вышеупомянутой документацией асинхронный материал не работает с IDispatch. Таким образом, мой интерфейс наследуется только от IUnknown. Однако метод GetInterfaceFromGlobal глобальной таблицы интерфейсов не работает с E_FAIL, когда интерфейс не помечен [dual], который, как я понимаю, должен наследовать от IDispatch. На этом этапе я оставил [dual], чтобы выполнить работу по маршалингу, но взял IDispatch в надежде на работу асинхронных вызовов. –

+0

также: добавлена ​​информация об ошибке –

ответ

0

Насколько я знаю, универсальный маршаллер не работает с асинхронным COM. Вам нужно создать (MIDL-сгенерированный) прокси (хотя, IIRC, вы можете объединить заглушки, если вы создаете DLL).

Вам также необходимо зарегистрировать прокси-библиотеку DLL (и создать ее с помощью определения -DREGISTER_PROXY_DLL). Для работы Async COM необходимы дополнительные ключи реестра.

Смежные вопросы