Windows 中的托管和非托管线程处理
所有线程的管理都是通过 Thread 类完成的,包括由公共语言运行时创建的线程以及在运行时以外创建并进入托管环境以执行代码的线程。 运行时监视其进程中曾经在托管执行环境中执行过代码的所有线程。 它不跟踪任何其他线程。 线程可以通过 COM 互操作(原因是运行时将托管对象作为 COM 对象向非托管领域公开)、COM DllGetClassObject 函数和平台调用进入托管执行环境。
当非托管线程进入运行时(如通过 COM 可调用包装)时,系统将检查该线程的线程本地存储区以查找内部托管 Thread 对象。 若找到一个对象,运行时就会注意到该线程。 但如果一个也找不到,则运行时将生成新的 Thread 对象并将其安装在该线程的线程本地存储区中。
在托管线程处理中, Thread.GetHashCode 是稳定的托管线程标识。 在线程的生存期内,它不会与来自其他任何线程的值相冲突,不管你是从哪个应用程序域获取该值。
从 Win32 线程处理到托管线程处理的映射
下表将 Win32 线程处理元素映射为其近似的运行时等效元素。 注意,此映射不表示具有相同的功能。 例如, TerminateThread 不执行 finally 子句或释放资源,并且不能被禁止。 但 Thread.Abort 可以执行所有回滚代码,回收所有资源,并可以使用 ResetAbort来拒绝。 请确保在对功能进行假设之前仔细阅读该文档。
在 Win32 中 | 在公共语言运行时中 |
---|---|
CreateThread | Thread 和 ThreadStart的组合。 |
TerminateThread | Thread.Abort |
SuspendThread | Thread.Suspend |
ResumeThread | Thread.Resume |
休眠 | Thread.Sleep |
线程句柄上的WaitForSingleObject | Thread.Join |
ExitThread | 无等效项 |
GetCurrentThread | Thread.CurrentThread |
SetThreadPriority | Thread.Priority |
无等效项 | Thread.Name |
无等效项 | Thread.IsBackground |
接近 CoInitializeEx (OLE32.DLL) | Thread.ApartmentState |
托管线程和 COM 单元
可以标记一个托管线程以指示它将承载一个 单线程 或 多线程 单元。 (有关 COM 线程处理体系结构的详细信息,请参阅 进程、线程和单元。)GetApartmentState 类的 SetApartmentState、TrySetApartmentState 和 Thread 方法返回并分配线程的单元状态。 如果未设置该状态,则 GetApartmentState 返回 ApartmentState.Unknown。
只有当线程处于 ThreadState.Unstarted 状态时才可以设置该属性;但一个线程只能设置一次。
如果在启动线程之前未设置单元状态,则该线程被初始化为多线程单元 (MTA)。 终结器线程和由 ThreadPool 控制的所有线程都是 MTA。
重要
对于应用程序启动代码,控制单元状态的唯一方式是将 MTAThreadAttribute 或 STAThreadAttribute 应用于入口点过程。
向 COM 公开的托管对象的行为就如同它们聚合了自由线程封送拆收器一样。 换言之,它们可以通过自由线程的方式从任何 COM 单元中调用。 唯一不显示这种自由线程行为的托管对象是那些从 ServicedComponent 或 StandardOleMarshalObject 派生的对象。
在托管领域中,不支持 SynchronizationAttribute ,除非使用上下文和上下文绑定的托管实例。 如果使用的是企业服务,对象必须派生自 ServicedComponent(它本身派生自 ContextBoundObject)。
当托管代码调用至 COM 对象时,它始终遵循 COM 规则。 换言之,它遵循 OLE32 的规定,通过 COM 单元代理和 COM+ 1.0 上下文包装来调用。
阻止问题
在阻止了非托管代码中的线程的操作系统中,如果线程进行非托管调用,则运行时将不会为 Thread.Interrupt 或 Thread.Abort控制该线程。 对于 Thread.Abort,运行时将该线程标记为 Abort ,并在重新进入托管代码时控制该线程。 使用托管阻止而不使用非托管阻止更为可取。 WaitHandle.WaitOne、WaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, Monitor.TryEnter, Thread.Join, GC.WaitForPendingFinalizers等都对 Thread.Interrupt 和 Thread.Abort做出响应。 而且,如果你的线程处于单线程单元,则当你的线程被阻止时,单元中的所有托管阻止操作都将正确发送消息。
线程和纤程
.NET 线程处理模型不支持纤程。 不得调用通过使用纤程实现的任何非托管函数。 此类调用可能会导致 .NET 运行时崩溃。