进行异步COM调用 - 我必须创建自己的P / S吗? [英] Making an async COM call -- do I have to create my own P/S?

查看:393
本文介绍了进行异步COM调用 - 我必须创建自己的P / S吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义接口在类型库中定义并在我的代码中实现。我没有创建我自己的代理/存根。我已经成功地将接口指针从我的主线程(STA)封送到后台线程(STA),在我的情况下使用 IGlobalInterfaceTable

I have a custom interface defined in a type library and implemented in my code. I have not created my own proxy/stub. I have successfully marshaled the interface pointer from my main thread (STA) to a background thread (STA), in my case using IGlobalInterfaceTable.

从这个背景线程,我想对UI上的对象进行异步调用线。我尚未在我的对象中实施 ICallFactory 。我看到标准代理确实实现了 ICallFactory (即,我可以成功地在后台线程上 ICallFactory )。但是我的自定义界面的 CreateCall 失败,并显示HRESULT 0x80040150 (无法从注册表中读取密钥)。

From that background thread, I want to make an asynchronous call to the object on the UI thread. I have not implemented ICallFactory in my object. I see that the standard proxy does indeed implement ICallFactory (i.e, I can successfully QI on the background thread for ICallFactory). But the CreateCall for my custom interface fails with HRESULT 0x80040150 (Could not read key from registry).

我需要创建自己的代理,显式实现 ICallFactory 为了这个?

Do I need to create my own proxy that explicitly implements ICallFactory in order to do this?

[
    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:

And here's the background thread proc in my unit test:

    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;
    }






推荐答案

据我所知,通用编组器不能使用Async COM。你需要构建(MIDL生成的)代理(虽然,IIRC,如果你正在构建一个DLL,你可以合并stub)。

As far as I know, the universal marshaller does not work with Async COM. You need to build the (MIDL-generated) proxy (although, IIRC, you can merge the stubs if you're building a DLL).

代理DLL(并使用-DREGISTER_PROXY_DLL定义构建它)。 Async COM需要定义更多的注册表项,以使其工作。

You also need to register the proxy DLL (and build it with the -DREGISTER_PROXY_DLL define). Async COM needs more registry keys defined in order to make it work.

这篇关于进行异步COM调用 - 我必须创建自己的P / S吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆