![](/img/trans.png)
[英]Registration-Free COM Interop: Deactivating activation context in finalizer throws SEHException
[英]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.