C# MTA控制台应用程序从多个线程调用STA COM对象
尽管有很多关于COM和STA/MTA的问题(例如),但大多数问题都是关于具有UI的应用程序。一、 但是,请执行以下设置:C# MTA控制台应用程序从多个线程调用STA COM对象,c#,com-interop,sta,mta,C#,Com Interop,Sta,Mta,尽管有很多关于COM和STA/MTA的问题(例如),但大多数问题都是关于具有UI的应用程序。一、 但是,请执行以下设置: 控制台应用程序,默认情况下是多线程单元(Main()显式具有[MTAThread]属性) 主线程生成一些工作线程 主线程实例化一个单线程COM对象 主线程调用Console.ReadLine(),直到用户点击“q”,然后应用程序终止 有几个问题: 许多地方提到了这个问题。我是否需要为主线程手动创建消息泵,或者如问题所示,CLR是否会在新的STA线程上为我创建消息泵 只是
- 控制台应用程序,默认情况下是多线程单元(Main()显式具有
属性)[MTAThread]
- 主线程生成一些工作线程
- 主线程实例化一个单线程COM对象
- 主线程调用Console.ReadLine(),直到用户点击“q”,然后应用程序终止
- 许多地方提到了这个问题。我是否需要为主线程手动创建消息泵,或者如问题所示,CLR是否会在新的STA线程上为我创建消息泵
- 只是为了确保——假设CLR自动创建了必要的管道,那么我可以从任何工作线程使用COM对象而不需要显式同步吗
- 以下哪项性能更好:
- 让CLR处理与COM对象之间的封送处理
- 在单独的STA线程上显式实例化该对象,并让其他线程通过(例如)与之通信
注意。COM和CLR的唯一深入解释是.NET和COM:Adam Nathan的完整互操作性指南(Sams,2002年1月)。但是它是基于.NET1.1的,现在已经绝版了(但是有Kindle版本,可以通过下载)。即使这本书也没有直接描述你想做什么。我会建议一些原型设计。这是由COM自动完成的。因为您的COM对象是单线程的,所以COM需要为该对象提供一个合适的主页,以确保以线程安全的方式使用它。由于主线程不够友好,无法提供这样的保证,COM会自动创建另一个线程并在该线程上创建对象。这个线程也会自动抽水,你不用做任何帮助。您可以看到它正在调试器中创建。启用非托管调试并查看“调试+窗口+线程”窗口。当您跳过新的调用时,您将看到线程被添加 很好,很简单,但它确实有一些后果。首先,COM组件需要提供代理/存根实现。帮助程序代码,知道如何序列化方法调用的参数,以便在另一个线程上进行真正的方法调用。这通常是提供的,但并不总是。如果缺少E_NOINTERFACE异常,您将得到一个难以诊断的E_NOINTERFACE异常。有时键入_E_libnotregisted,这是一个常见的安装问题 最重要的是,COM组件上的每个调用都将被封送。这很慢,封送调用通常比直接调用花费很少时间的方法慢10000x左右。就像一个属性getter调用。这当然会让你的计划陷入困境 STA线程可以避免这种情况,因此建议使用单线程组件。是的,STA线程需要泵送消息循环。.NET程序中的Application.Run()。它是消息循环,用于封送COM中从一个线程到另一个线程的调用。请注意,这并不一定意味着您必须有一个消息循环。如果不需要封送任何调用,或者换句话说,如果从同一线程对组件进行所有调用,则不需要消息循环。这通常很容易保证,尤其是在一家公司