单线程套间(STAThread) vs. 多线程套间(MTAThread )

[原文链接]:  STA Thread vs. MTAThread(WHost)

 

          最近我遇到一个有趣的线程问题,想跟大家分享一下,以免大家也遇到这种容易混淆的问题。

          打开一个其他人写的C#程序,为了下面的讲解,我把这个程序叫作”DeltaEngine”DeltaEngine会调用一个本地的程序集,并处理其中某些事件。然后建一个工程,把DeltaEngine作为库项目引用,这个工程又被一个VB程序引用。我把这个VB程序叫做"VBApp"所以,引用结构就像: 

         VBApp (VB) -> DeltaEngine (C#) -> NativeCode

      当我把VBApp作为启动程序运行时,它会一直等待NativeCode里面的事件在DeltaEngine中被处理。我注意到,如果我把DeltaEngine作为启动程序来运行的话,事件就会像预期那样得到处理。我花了很多时间想解决这个问题,但还是很困惑。

      最后有人指出,VB目的默认线程模型是单线程套间(SingleThreaded  Apartment),而C#项目的默认线程模型是多线程套间 (Multithreaded Apartment)因为DeltaEngine最初是作为C#工程开发的,被默认为使用MTA。当使用VBApp作为启动程序调用DeltaEngine时,DeltaEngine就会使用STA因为这样,DeltaEngine就会开始等待其实它已经唤起的事件,所以DeltaEngine会一直等待下去。如果我把DeltaEngine作为启动程序运行,它就会使用MTA并且会像预期那样工作。

      解决的方法就是把MTAThreadAttribute加进VBApp的主函数里面。如下:

    <MTAThread> Sub Main()

      类似,如果你想把STAThread attribute加进C#的主方法里面,如下:

      [STAThread]

      static void Main()

      WindowsForms程序要求使用STA,所以创建C# Winapp后,你可以在Program.cs看见像这样的代码。

      我就不重复一些已经有的关于STATread MTAThread的文件,所以我给出下面的一些link可以学到更多关于STATread MTAThread的东西。

     STAThreadAttribute

      http://msdn2.microsoft.com/en-us/library/system.stathreadattribute(VS.71).aspx                           

      http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx

      MTAThreadAttribute

      http://msdn2.microsoft.com/en-us/library/system.mtathreadattribute(VS.71).aspx