C# 如何在从第三方非托管进程调用托管插件的所有线程上强制执行MTA?

C# 如何在从第三方非托管进程调用托管插件的所有线程上强制执行MTA?,c#,multithreading,com-interop,sta,mta,C#,Multithreading,Com Interop,Sta,Mta,我正在尝试使用COM互操作将托管插件写入非托管主机应用程序。非托管插件接口都是COM兼容的,尽管没有使用COM(没有注册表等)。我已经走了很长一段路来让它发挥作用,我只想改变一件事 从非托管主机应用程序到托管插件程序集的调用都是在STA-(托管)线程上进行的。我希望它是MTA,因此没有同步/泵送开销 我找不到实现这一目标的方法 任何帮助或建议都是非常宝贵的 编辑:这不是常见的COM互操作场景:主机不是COM,没有人调用CoInitialize/CoCreateInstance等。CLR似乎确实将

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

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

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

任何帮助或建议都是非常宝贵的

编辑:这不是常见的COM互操作场景:主机不是COM,没有人调用CoInitialize/CoCreateInstance等。CLR似乎确实将单元分配给调用托管插件的非托管线程。这就是我想要改变的(它现在默认为STA而不是MTA)

我提出的相关问题可能提供更多的背景:

您在这件事上没有发言权,是非托管主机应用程序创建了线程并调用了CoInitializeEx(),选择了单元类型。以后不能更改

这不是什么大问题,因为如果您对MTA的呼叫没有意见,建议您支持免费线程。NET ComVisible类的默认ThreadingModel为两者。因此,当主机从其STA线程调用您时,不会发生封送处理,使用错误的STA线程是非常不寻常的


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

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

导出的函数是如何实现的?我想在插件中有一段非托管C++代码来引导托管代码。如果是这样,理论上,您可以在这里执行
coinitializex(NULL,COINIT\u多线程)
。也就是说,您应该在从C++通过COM互操作创建任何.NET对象之前做这件事。p> 然而,对于主机应用程序来说,这样做可能是非常不负责任和危险的。您是否绝对确定主机在此线程上不使用COM(也不使用任何其他插件)?您确定它不会在稍后的某个阶段尝试初始化COM吗


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

正如我在文章中试图描述的,只有接口与COM兼容。其余部分不是COM,主机应用程序中不调用CoInitialize!此外,没有(托管的)COM组件——它只是传递接口(指针)。托管插件的入口点是导出的函数。当它被调用时,它已经是STA了。我明白它不能在事后更改-所以我的问题是如何在手之前更改它…嗯,第一句话应该没有什么疑问。您必须与宿主程序的程序员取得联系,并要求他更改代码。他会像我对待你的否决票一样对待你的请求,覆盆子。如果我伤害了你的感情,我很抱歉,但从你现在的回答来看,这没有用,也没有建议联系最初的程序员。谢谢你的帮助。@obiwanjacobi答案可能没有帮助,但它是正确的。如果只需要在某些条件下调用代码,则需要与调用者协作以确保满足这些条件。既然你说你没有使用COM,COM也帮不了你。主机没有使用COM,但我使用COM互操作来进行互操作。它之所以有效,是因为接口是COM兼容的。唯一的问题是CLR会自动将(线程)调用标记到我的托管插件中作为STA。我的问题是这是否可以改变?所以这不是一个普通的COM互操作场景。没有人调用CoInitialize(除了CLR本身?),也没有人使用CoCreateInstance等。下面是我用来导出托管函数的DllExport属性。它使用导出方法的一些额外IL标志重写程序集。没有非托管互操作/thunking代码发挥作用。是的,我绝对100%肯定主机不会也永远不会使用COM。我知道你不能在事后更改公寓-这就是为什么我在寻找一种方法来告诉CLR该怎么做…@obiwanjacobi,那么你是否尝试过在入口点开始时通过p/invoke显式调用
coinitializex(NULL,COINIT\u multi-threaded)