繁体   English   中英

免注册的类COM互操作和线程

[英]Registration-free COM-like interop and threading

我正在使用具有WPF GUI和非托管C ++后端的桌面应用程序。 我已经通过以下方式定义了API(C#版本,已截断):

[Guid( "###" ), InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
interface iMyApp
{
    void aMethod();
}
[DllImport( "my.dll", PreserveSig = true )]
public extern static int create( string configPath, out iMyApp a );

在后端我有

__interface __declspec( uuid( "###" ) ) iMyApp: public IUnknown
{
    HRESULT __stdcall aMethod();
}

和经典的基于ATL的实现。

这很好并且快速,不需要COM注册,类型库,MIDL编译器等。

问题是,我无法在C#中跨线程传递iMyApp实例,从而引发E_NOINTERFACE异常。

我的实现是线程中立的。

如何告诉.NET,以便它停止在线程间编组接口,而仅在所有线程上使用相同的IUnknown指针? 如果有问题,我只需要支持4.5+

正如Hans Passant所暗示的,此处的关键是CoCreateFreeThreadedMarshaler API。

添加一个私有变量CComPtr<IUnknown> m_ftm;

初始化该编组器:

HRESULT FinalConstruct()
{
    IUnknown* pUnk = GetUnknown();
    return CoCreateFreeThreadedMarshaler( pUnk, &m_ftm );
}

通过将以下行添加到接口映射,在QueryInterface中处理IID_IMarshal:

COM_INTERFACE_ENTRY_AGGREGATE( IID_IMarshal, m_ftm )

之后,C#代码将愉快地从任何线程调用那些对象。 当然,您必须自己处理同步, CComAutoCriticalSection / CComCritSecLock通常可以提供帮助。

更新: MS在VS 2017中破坏了我的代码,更新了答案。 请参阅VS2015版本的编辑历史记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM