首次使用COM 我有这个COM DLL,比如ABCServer.dll,我创建了一个RCW,并在我的项目中添加了对它的引用。现在我的应用程序创建了几个线程,每个线程从COM dll创建某些类并使用它们。但是,当其他线程正在使用来自COM dll的某个类时,每个线程都在等待。
修改我的应用程序的整个目的是在其上启用多线程。现在,当多边线程发生在我身边时,COM导致它是顺序的。虽然每个线程都在创建新实例,但为什么还要等待其他实例处理呢?
答案 0 :(得分:4)
如果您的COM组件标记为STA (single-threaded apartment),那么您无法做任何事情来使其成为多线程的;组件的要求是所有对它的调用都被序列化到STA所在的线程上,而COM会自动为你处理。
那就是说,如果你的组件是一个STA组件(看起来是这样),你就不能将它改为multi-threaded apartment component (MTA)甚至更好,free-threaded(所以没有公寓之间的编组)因为a)它是用VB6编写的,或者b)它是第三方dll,那么你可能最好使用某种排队模型。
基本上,让所有其他工作异步运行,然后有一个线程(或进程,由你决定),这将消耗一次一个地调用这个组件的请求,尽管如此(请注意,您可以在多个线程中实例化此组件的多个实例,您只需确保将ApartmentState
property on the Thread
class设置为ApartmentState.STA
),然后在调用时发布事件/回调完成并异步完成其他工作。
它基本上就像有两个生产者/消费者实现,一个用于调用COM组件,另一个用于在完成后调度结果。
答案 1 :(得分:1)
到目前为止,评论和答案中存在相当大的混淆。 STA或MTA是线程的属性。但重要的是COM组件需要什么。这是在ThreadingModel注册表值中声明的。你找到了“公寓”,这是一个非常常见的环境。这意味着该组件不支持线程。
这与.NET框架中的绝大多数类没有什么不同,很少有线程安全的。最大的区别是COM 强制执行线程安全。使用.NET类,您可以编写代码,以便以线程安全的方式使用类对象。这很难做到正确并且是一个非常难以诊断的错误来源,但设计良好的锁定可让您绕过限制。对于COM来说这是不可能的,它将始终提供线程安全,而无需您的帮助。即使你确实想帮忙。
获得成功的唯一方法是仅从一个线程创建和使用COM组件。必须使用Thread.SetApartmentState()初始化该线程以选择STA。这阻止了COM创建自己的线程来为组件找到安全的避风港。并且您必须提供消息循环,STA要求。如果您不尝试使用来自另一个线程的COM组件并且组件本身不依赖于具有可用的消息泵,那么这可能是痛苦的并且可能可以避免。这是非常常见的顺便说一句。您会注意到它在停止响应时需要一个,通常不会在预期时触发事件。只能从同一个线程调用COM对象,以便与创建自己的对象的其他线程实现并发。这通常不是很有用或不可能。
答案 2 :(得分:1)
如果每个线程都在创建自己的Apartment-model对象实例,并且每个线程都标记为在STA中运行,那么每个线程应该在它自己的独立STA中,并且您的COM对象实例应该在单独的STA。
我认为其他答案假设您的COM实例都在同一个公寓中。如果调用Thread.SetApartmentState()以确保每个线程在创建COM对象实例之前都在STA中,那么该线程的COM对象应该存在于该线程的STA中,该STA与其他线程的STA分开。然后,您不应该看到对不同STA中对象的任何调用序列化。