У меня есть пользовательский интерфейс, определенный в библиотеке типов и реализованный в моем коде. Я не создал свой собственный прокси-сервер. Я успешно обработал указатель интерфейса из основного потока (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;
}
Показать, как вы называете 'CreateCall'. С какой ошибкой это происходит? Кроме того, есть ли у вашего интерфейса двойной интерфейс (исходящий из 'IDispatch'), случайно? Из [этой части документации] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms692623.aspx): «** Примечание ** Асинхронная поддержка недоступна для' IDispatch' или для интерфейсы, наследующие 'IDispatch'. –
Я видел эту документацию и действовал соответствующим образом. Однако, я думаю, что нарушаю правила. В соответствии с вышеупомянутой документацией асинхронный материал не работает с IDispatch. Таким образом, мой интерфейс наследуется только от IUnknown. Однако метод GetInterfaceFromGlobal глобальной таблицы интерфейсов не работает с E_FAIL, когда интерфейс не помечен [dual], который, как я понимаю, должен наследовать от IDispatch. На этом этапе я оставил [dual], чтобы выполнить работу по маршалингу, но взял IDispatch в надежде на работу асинхронных вызовов. –
также: добавлена информация об ошибке –