2011-10-28 96 views
4

第一次使用COM 我有这个COM DLL,说ABCServer.dll,我创建了一个RCW并在我的项目中添加引用它。现在我的应用程序创建了多个线程,每个线程都从COM DLL创建某些类并与它们一起工作。但是,然后每个线程正在等待,而其他线程正在从COM DLL的某些类工作。COM多线程支持

修改我的应用程序的整个目的是启用多线程。现在当多线程发生在我身边时,COM使它成为顺序的。虽然每个线程都在创建新实例,但他们为什么还在等待其他人被处理?

+0

是您的COM组件声明单线程单元(STA)或者多线程公寓(MTA)? – Seb

+0

如何以及在哪里检查? – EagerToLearn

+0

@EagerToLearn看到http://stackoverflow.com/questions/2722867/how-to-determine-threading-model-of-given-com-library – shf301

回答

1

到目前为止发布的评论和答案中存在相当大的混淆。 STA或MTA是线程的属性。但重要的是COM组件需要什么。这是在ThreadingModel注册表值中声明的。你找到了“公寓”,这是一个非常普遍的设置。这意味着该组件不支持线程。

这与.NET框架中的绝大多数类没有什么不同,很少有线程安全的。最大的区别是COM 强制执行线程安全性。使用.NET类,您需要编写代码,以便以线程安全的方式使用类对象。这是很难得到正确的,并且很难诊断错误的慢性源,但精心设计的锁定允许您绕过限制。这对于COM来说是不可能的,它将始终提供线程安全性,而无需您的帮助。即使你确实想帮忙。

获得进展的唯一方法是仅从一个线程创建和使用COM组件。该线程必须使用Thread.SetApartmentState()来初始化以选择STA。这可以防止COM创建自己的线程为组件寻找安全的避风港。你必须抽出一个消息循环,一个STA要求。如果您不尝试使用来自其他线程的COM组件,并且组件本身不依赖于消息泵可用,那么这可能会很痛苦,并且可能会被避免。这是很常见的顺便说一句。当它停止响应时,您会注意到它需要一个响应,通常在预期时不会触发一个事件。只从同一个线程对COM对象进行调用才能获得与创建自己对象的其他线程的并发。这通常不是有用或可能的。

4

如果你的COM组件被标记为STA (single-threaded apartment)那么你就没有办法让它成为多线程的;组件的要求是所有对它的调用都被串行化到STA所在的线程上,并且COM自动为你处理。这就是说,如果你的组件是一个STA组件(它看起来就是这样),你不能将它改为multi-threaded apartment component (MTA)甚至更​​好,因为根本就没有公寓之间的编组,所以因为你不能将它改变成multi-threaded apartment component (MTA) a)它是用VB6编写的,或者b)它是第三方的dll,那么使用某种排队模型可能会更好。

基本上把所有的其他工作运行的异步,然后有一个线程(或过程,它是由你),这将消耗请求调用此组件一次一个,尽可能快,因为它可以(请注意,您可以在多个线程中实例化此组件的多个实例,您只需确保将ApartmentState property on the Thread class设置为ApartmentState.STA),然后在调用完成时发布事件/回调并异步继续其他工作。

它基本上就像拥有两个生产者/消费者实现,一个将调用分派给COM组件,另一个实现时分派结果。

1

如果每个线程的创建其自己的公寓模型对象的实例,每个线程被标记在STA中运行,那么每个线程应该在它自己单独的STA和你的COM对象实例应该运行在单独的STA中。

其他的答案在这里假设,我认为,你的COM实例都在同一所公寓。如果调用Thread.SetApartmentState()以确保每个线程在创建COM对象实例之前都在STA中,那么该线程的COM对象应该位于该线程的STA中,该STA与其他线程的STA分离。您不应该看到任何对不同STA中对象的调用序列化。

+0

我会告诉你最新的发现,COM DLL使用JVM连接到服务器并提交/接收请求/响应文件。如果我运行应用程序的两个实例,远程服务器日志显示创建了两个会话,而当我在应用程序的单个实例中使用多个请求时,JVM日志显示请求以排队方式提交给服务器,服务器日志显示只有一个会话被创建。我知道可以有一万个理由,但专家可能会导致靶心 – EagerToLearn

+0

好吧,即使你所有的COM对象在同一个STA,并呼吁他们分别被序列化,那将不能解释为什么你只有一个会话服务器。这听起来像是你的COM对象中有逻辑管理每个进程的单个会话。 – Martin

+0

是的,它显得那么,当两个应用程序实例(每个都有自己的COM引用DLL)运行时,则使用两个交易日,而只有一个,当我们有一个实例内的多个请求(其COM参考DLL)用于 – EagerToLearn