技术开发 频道

重用托管代码中的Classic COM 组件


   这就是上面程序的输出:
HANGGLIDER: CLEARED TO TAKEOFF 
CFlyer::TakeOff - This is COM taking off
In HangGlider::Fly - Before delegating to flyer.Fly
CFlyer::Fly - This is COM in the skies
    在上面的例子中,HangGlider类型创建了Flyer COM组件的一个实例,把它作为一个专用成员储存起来。无论什么时候,当方法调用到达时,就要求Flyer组件服务,通过使用被它在前面中断专用实例,它调用组件。而且,在调用被委派到Flyer组件方法之前或者之后,HangGlider类型能自由输入代码。除非在托管类型中覆盖了所有的基本类型,否则混合模式继承重用类型不可能完成这一任务。

从.NET应用程序的角度了解COM线程模式和单元

    当我第一次用COM 编辑程序时不敢冒险使用COM线程模式和apartments ,而且也不知道它们到底是什么。我认为自由地编辑项目是非常好,而且假设它是最好的程序编辑线程模式。但是我几乎没有感知到简单的外表下面发生了什么。由我的MTA对象创建的STA客户端线程时,可能回导致性能终结。而且,因为对象并不是多线程安全,我从不知道当并行线程访问对象时,可能会陷入麻烦。在那个时候,忽视COM 线程模式真的是一种幸福。但是那种幸福只是短暂的,服务器开始出乎意外地崩溃。然后不得不学习COM 线程模式,学习每一个模式是怎样工作的,以及COM 托管单元是怎样工作的,当调用两个不相容的单元时,性能蕴含式会产生什么。在线程调用COM对象之前,通过宣告它是否会输入一个STA或者MTA. STA客户端线程调用CoInitialize(NULL)或者CoInitializeEx(0, COINIT_APARTMENTTHREADED),以此来输入一个STA单元,或者是宣告它是否会输入一个MTA线程调用CoInitializeEx(0, COINIT_MULTITHREADED),以此来输入一个MTA ,以此方式来宣告它自己与单元相联系。相似地,在.NET 托管世界中,你可以允许托管空间里的调用线程宣告它与单元相联系。通过默认,托管 应用程序里的调用线程选择居住在MTA 中。就好像用CoInitializeEx(0, COINIT_MULTITHREADED)初始化了它自己。但是考虑一下开销和性能终结,如果调用一个classic STA COM 组件, 此STA COM 组件被设计成线程单元,就会招致开销和性能终结。不相容的单元将导致额外的代理/存根的开销,很明显,这就是性能终结。通过使用System.Threading.Thread类型里的ApartmentState属性,在.NET应用程序里,你可以为托管线程覆盖单元的默认选择。ApartmentState属性执行下面其中一个枚举 值:MTA, STA以及Unknown. ApartmentState.Unknown相当于默认MTA行为。在调用COM对象之前需要将调用线程指定ApartmentState。一旦COM对象创建了,就不可能改变ApartmentState。因此,尽可能早地在代码中建立线程ApartmentState是非常有意义的。

// 设置用户线程 
Thread.CurrentThread.ApartmentState = ApartmentSTate.STA;

// 创建COM对象
MySTA objSTA = new MySTA();
objSTA.MyMethod()
    作为另一个可以选择的方法,你可以用STAThreadAttribute 或者MTAThreadAttribute标记你的托管客户端主入口点方法,首先以建立完美的线程辅助开始,以此来使用COM组件。例如,看下面的代码片段:

public class HelloThreadingModelApp { 

.....

[STAThread]
static public void Main(String[] args) {

System.Console.WriteLine("The apartment state is: {0}",
Thread.CurrentThread.ApartmentState.ToString());

}/* 结束Main */

}/* 结束class */
   你得到的输出可能是这样的:

The apartment state is: STA
    如果创建了MTAThread属性,然后在MTA上建立ApartmentState。如果客户端主入口点中没有指定线程状态属性,或者如果从被创建的COM组件中,没有为线程创建ApartmentState属性,然后就不会知道ApartmentState,ApartmentState 不执行MTA行为。
0
相关文章