0

我正在尝试使用 COM 互操作将托管插件写入非托管主机应用程序。尽管没有使用 COM(没有注册表等),但非托管插件接口都与 COM 兼容。我已经走了很长一段路要让它发挥作用,我只想改变一件事。

从非托管主机应用程序到托管插件程序集的调用都是在 STA-(托管)线程上进行的。我希望它是 MTA,因此没有同步/泵送开销。

我找不到实现这一目标的方法。

任何帮助或建议都是最受赞赏的。

编辑:这不是常见的 COM 互操作方案:主机不是 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

4

2 回答 2

1

您提到主机应用程序中不涉及 COM,并且托管插件的入口点是导出的函数

导出的功能是如何实现的?我想你的插件中有一段非托管的 C++ 代码来引导托管代码。如果是这样,CoInitializeEx(NULL, COINIT_MULTITHREADED)理论上你可以这样做。也就是说,您应该在通过 COM 互操作从 C++ 创建任何 .NET 对象之前执行此操作。

但是,这样做对于主机应用程序而言可能是非常不负责任和危险的。您是否绝对确定主机不在此线程上使用 COM(因此它的任何其他插件也不使用)?您确定它不会在以后的某个阶段尝试初始化 COM 吗?

此外,如果主机已经将此线程上的 COM 初始化为 STA,则您的调用CoInitializeEx很可能会因RPC_E_CHANGED_MODE错误而失败。

于 2013-12-30T22:46:41.860 回答
0

你在这件事上没有发言权,它是创建线程并调用 CoInitializeEx() 的非托管主机应用程序,选择了公寓类型。之后无法更改。

这不是什么大问题,因为如果您可以接受来自 MTA 的调用,您建议您支持免费线程。.NET ComVisible 类的默认 ThreadingModel 是 Both。因此,当主机从其 STA 线程调用您时,不会发生封送处理,它使用错误的 STA 线程将是非常不寻常的。

仅当您对非托管主机进行回调时才重要,事件是最常见的情况。您可以在自己的代码中使用线程,但您必须遵守主机要求的合同。您进行的任何回调都必须在创建类的线程上执行。使用 Control.BeginInvoke() 很简单,主机承诺支持它,因为它选择了 STA。例如,与 WebBrowser.DocumentCompleted 事件进行比较。

于 2013-12-29T13:59:10.650 回答