(一)引经据典(MSDN):
1.单元是进程内部具有相同线程访问要求的对象的逻辑容器。同一单元中的所有对象都可以接收从该单元中的任何线程发出的调用。.NET Framework 不使用单元,托管对象自己负责以线程安全的方式使用所有共享资源。
由于 COM 类使用单元,因此公共语言运行库需要在 COM interop 的情况下调用 COM 对象时创建并初始化一个单元。托管线程可以创建并进入只允许有一个线程的单线程单元 (STA) 或者包含一个或多个线程的多线程单元 (MTA)。通过将线程的 ApartmentState 属性设置为 ApartmentState 枚举值之一,可以控制所创建的单元的类型。由于给定线程只能初始化 COM 单元一次,因此在第一次调用非托管代码之后就不能更改单元类型。
2.public enum ApartmentState
成员
MTA Thread 将创建并进入一个多线程单元。
STA Thread 将创建并进入一个单线程单元。
Unknown 尚未设置 ApartmentState 属性。
3.Sample:
(二)其他方法问题产生的原因:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisible(true)]
如果在主线程中,在入口添加[STAThread]:
[STAThread]
是一种线程模型,用在程序的入口方法上(在C#和VB.NET里是Main()方法),来指定当前线程的 ApartmentState 是STA。用在其他方法上不产生影响。在aspx页面上可以使用AspCompat = "true" 来达到同样的效果。这个属性只在 Com Interop 有用,如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。
(三)特定环境特定条件
由于一些特殊原因,我需要在一个没有GUI的程序中启动屏幕保护程序,因此最初使用的是System.Threading.Timer来做定时器的,但是在测试中发现总是出席以下异常:
Message: 因为当前线程不在单线程单元中,故无法实例化 ActiveX 控件“6bf52a52-394a-11d3-b153-00c04f79faa6”。
Source: System.Windows.Forms
at System.Windows.Forms.AxHost..ctor(String clsid, Int32 flags)
at System.Windows.Forms.AxHost..ctor(String clsid)
at AxWMPLib.AxWindowsMediaPlayer..ctor()
...
这个是某兄博客上的, 。
后来弄了好长时间才发现,原来WindowsMediaPlayer控件只能在单线程环境下才可以运行,后来将我的Timer改成System.Windows.Forms.Timer对象,再进行测试,一切OK!
(四) 待大家补充啊