我正在尝试使用COM互操作将托管插件写入非托管主机应用程序。虽然没有使用COM(没有注册表等),但非托管插件接口都兼容COM。我已经走了很长的路要走,我想改变一件事。
从非托管主机应用程序进入托管插件程序集的调用都是在STA(托管)线程上进行的。我希望它是MTA所以没有同步/泵送开销。
我无法找到实现这一目标的方法。
任何帮助或建议都是最值得赞赏的。
编辑:它不是一个常见的COM-interop场景:主机不是COM,没有人调用CoInitialize / CoCreateInstance等。似乎CLR确实将公寓分配给调用托管插件的非托管线程。这就是我想要改变的东西(它现在默认为STA而不是MTA)。我提出的相关问题可能会提供更多背景信息: Interop COM(-isch) interface marshaling results in AccessViotlationException on simple call Returned managed object method not called from C++ in COM interop
答案 0 :(得分:1)
您提到主机应用中没有涉及COM,而您的托管插件的入口点是导出的功能。
如何实施导出功能?我想你的插件中有一段非托管的C ++代码来引导托管代码。如果是这样,那么理论上你可以做CoInitializeEx(NULL, COINIT_MULTITHREADED)
。也就是说,您应该在通过COM interop从C ++创建任何.NET对象之前执行此操作。
但是,对于主机应用程序而言,这样做可能是非常不负责任和危险的。你绝对确定主机不在这个线程上使用COM(所以不要使用其他任何插件)吗?你确定它不会在稍后阶段尝试初始化COM吗?
此外,如果主机已将此线程上的COM初始化为STA,则对CoInitializeEx
的调用很可能会因RPC_E_CHANGED_MODE
错误而失败。
答案 1 :(得分:0)
你没有发言权,是非托管主机应用程序创建了线程并调用了CoInitializeEx(),选择了公寓类型。之后无法更改。
这不是什么大问题,因为如果您对来自MTA的电话没问题,建议您支持免费线程。 .NET ComVisible类的默认ThreadingModel是Both。因此,当主机从其STA线程调用您时,不会发生编组,它使用错误的STA线程将是非常不寻常的。
只有在回调到非托管主机时,才会发生事件,事件是最常见的情况。您可以在自己的代码中使用线程,但必须遵守主机要求的合同。您创建的任何回调必须在创建类的线程上执行。与Control.BeginInvoke()一样简单,主机承诺支持它,因为它选择了STA。例如,与WebBrowser.DocumentCompleted事件进行比较。