一.什么叫做套间,套间有什么特点.
一个抽象概念,建立了对象与进程线程之间的相互关系.一个对象实例只属于一个套间,一个套间可包含多个对象实例;一个进程只能有一个MTA,可以有多个STA;一个套间可以"包含"多个线程,一个线程只属于一个套间;进程内激活的对象属于MTA还是STA是根据对象本身特性决定的(ThreadingModel特性:free->MTA,both->MTA||STA,Apartment->STA,没有这个特性->主STA(进程创建的第一个STA)),而不是根据激活该对象的线程从属的套间决定.CoInitializeEx可以决定调用该方法的线程属于MTA还是STA,在激活对象时,如果线程从属的套间和对象的threadingmodel特性冲突,COM将根据对象的threadingmodel特性在相应的套间中产生对象的实例,并返回一个该对象实例的代理,否则,COM将在线程从属的套间中创建对象的实例(这是效率最高的情形,因为不用使用代理).
二. MTA
不同的线程可以访问在同一STA中的同一对象实例,同一时刻,同一MTA中允许多个线程并行执行.因此在MTA中的对象不仅要保护全局和静态变量,还要保护对象成员变量.
三.STA
在STA中,同一对象实例和线程是一一对应关系(即一个线程不能访问另一个线程创建的对象实例),同一时刻,同一STA中只允许一个线程执行,因此对象的实现者只需要保护对象的全局和静态变量(同一对象的不同实例可能在不同的STA中),由于同一对象的多个实例可能存在于同一个STA中,虽然同一STA中的线程不能并行执行,但调用同一对象的不同实例可以修改静态和全局变量,后面修改的值将覆盖前面的值,而前面的对象实例并未发觉,这是很危险的.线程的数量不能超过本套间中对象实例的数量.
注:
从编程角度来说,COM只是一套编程的规范。当你按照COM的规范来写代码的时候,COM runtime保证你的代码不出问题;反之,如果你不按照COM的规范来写代码,那么COM runtime是不保证你的代码能正确得到COM库提供的 服务 的。拿线程的安全性来说,COM runtime通过装载合适的Proxy/stub来检查保证线程的安全性。要保证COM runtime装载合适的Proxy/stub,你必须遵守COM的线程规范。比如跨apartment的时候必须marshal接口指针而不能直接传接口指针等等。如果你直接传接口指针,COM runtime将不会装载对应的proxy,从而COM runtime的线程安全服务也就无从谈起。
Client code running in a process and/or thread that uses the STA model must marshal interfaces of an object between apartments by using CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream. For example, if Apartment 1 in the client has an interface pointer, and Apartment 2 requires use of it, Apartment 1 must marshal the interface using CoMarshalInterThreadInterfaceInStream. The stream object returned by this function is thread-safe and its interface pointer should be stored in a direct memory variable accessible by Apartment 2. Apartment 2 must pass this stream interface to CoGetInterfaceAndReleaseStream to unmarshal the interface on the underlying object and get back a pointer to a proxy through which it can access the object.
-微软全球技术中心 VC技术支持