发生了类型为"System.Runtime.InteropServices.COMException"的异常。接口未注册(来自 HRESULT 的异常:0x80040155)



我试图从不同的线程使用COM对象,我得到这个错误。同样的错误不会发生在单线程模型中。

可能的原因是什么?

我尝试用CComMultiThreadModel实现接口。

您还没有为COM对象注册代理/存根对象,因此它的接口无法被编组到有问题的线程。

你有两个选择A)注册代理。如果接口是你的应用私有的,你可以合并代理存根。如果它们不是,您应该创建一个单独的DLL。ATL向导可以帮助您生成代理,所以很可能您已经拥有了代理,只是没有安装/注册它们。

代理将确保对对象的调用发生在它注册的同一个COM单元中。在您的情况下,是STA。这也减少了对锁的需求——因为代码中一次只有一个调用。http://msdn.microsoft.com/en-us/library/ms809971.aspx

当然,您仍然需要防止重入,因为您的STA对象可能在其呼出期间被重入。http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx

使用代理的缺点是在编组和等待STA方面都有性能成本。

在经典的Win32模型中,你应该总是使用STA来封装UI的COM对象,因为hwnd总是绑定到单个线程。

b)聚合自由线程编组程序。您还可以在ATL中找到这个选项。自由线程编组器允许从进程中的任何单元直接调用COM对象。http://msdn.microsoft.com/en-us/library/windows/desktop/ms694500 (v = vs.85) . aspx

当您使用FTM时,对对象的调用是直接的虚函数调用-不涉及编组。

选择此选项要求您使代码线程安全(通过应用适当的锁定),因为调用现在可能同时来自多个线程。

一个额外的负担是FTM对象不能直接持有接口指针,除非它确定这些对象也聚合了FTM。因此,当您从其他人那里获得IUnknown时,您需要将其存储为与公寓无关的格式(例如在全局接口表中)。

由于这个和其他原因,对于知道自己在做什么的人来说,FTM是一个高级的选择。但它也是非ui代码的最高性能选择。

Martyn

相关内容

最新更新