多线程
线程 被定义为程序的执行门路。每个线程都定义了一个独特的控制流。如果您的应用程序波及到简单的和耗时的操作,那么设置不同的线程执行门路往往是无益的,每个线程执行特定的工作。
线程是轻量级过程。一个应用线程的常见实例是古代操作系统中并行编程的实现。应用线程节俭了 CPU 周期的节约,同时进步了应用程序的效率。
到目前为止咱们编写的程序是一个单线程作为应用程序的运行实例的繁多的过程运行的。然而,这样子应用程序同时只能执行一个工作。为了同时执行多个工作,它能够被划分为更小的线程。
线程生命周期
线程生命周期开始于 System.Threading.Thread 类的对象被创立时,完结于线程被终止或实现执行时。
上面列出了线程生命周期中的各种状态:
- 未启动状态:当线程实例被创立但 Start 办法未被调用时的情况。
- 就绪状态:当线程筹备好运行并期待 CPU 周期时的情况。
- 不可运行状态:上面的几种状况下线程是不可运行的:
- 曾经调用 Sleep 办法
- 曾经调用 Wait 办法
- 通过 I/O 操作阻塞
死亡状态:当线程已实现执行或已停止时的情况。
主线程
在 C# 中,System.Threading.Thread 类用于线程的工作。它容许创立并拜访多线程应用程序中的单个线程。过程中第一个被执行的线程称为主线程。
当 C# 程序开始执行时,主线程主动创立。应用 Thread 类创立的线程被主线程的子线程调用。您能够应用 Thread 类的 CurrentThread 属性拜访线程。
上面的程序演示了主线程的执行:
实例
using System;using System.Threading;namespace MultithreadingApplication{ class MainThreadProgram { static void Main(string[] args) { Thread th = Thread.CurrentThread; th.Name = "MainThread"; Console.WriteLine("This is {0}", th.Name); Console.ReadKey(); } }}
当下面的代码被编译和执行时,它会产生下列后果:
This is MainThread
Thread 类罕用的属性和办法
下表列出了 Thread 类的一些罕用的 属性:
属性 形容
- CurrentContext 获取线程正在其中执行的以后上下文。
- CurrentCulture 获取或设置以后线程的区域性。
- CurrentPrincipal 获取或设置线程的以后负责人(对基于角色的安全性而言)。
- CurrentThread 获取以后正在运行的线程。
- CurrentUICulture 获取或设置资源管理器应用的以后区域性以便在运行时查找区域性特定的资源。
- ExecutionContext 获取一个 ExecutionContext 对象,该对象蕴含无关以后线程的各种上下文的信息。
- IsAlive 获取一个值,该值批示以后线程的执行状态。
- IsBackground 获取或设置一个值,该值批示某个线程是否为后盾线程。
- IsThreadPoolThread 获取一个值,该值批示线程是否属于托管线程池。
- ManagedThreadId 获取以后托管线程的惟一标识符。
- Name 获取或设置线程的名称。
- Priority 获取或设置一个值,该值批示线程的调度优先级。
- ThreadState 获取一个值,该值蕴含以后线程的状态。
下表列出了 Thread 类的一些罕用的 办法:
序号 办法名 & 形容
1 public void Abort()
在调用此办法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此办法通常会终止线程。
2 public static LocalDataStoreSlot AllocateDataSlot()
在所有的线程上调配未命名的数据槽。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
3 public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
在所有线程上调配已命名的数据槽。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
4 public static void BeginCriticalRegion()
告诉主机执行将要进入一个代码区域,在该代码区域内线程停止或未经解决的异样的影响可能会危害应用程序域中的其余工作。
5 public static void BeginThreadAffinity()
告诉主机托管代码将要执行依赖于以后物理操作系统线程的标识的指令。
6 public static void EndCriticalRegion()
告诉主机执行将要进入一个代码区域,在该代码区域内线程停止或未经解决的异样仅影响当前任务。
7 public static void EndThreadAffinity()
告诉主机托管代码已执行完依赖于以后物理操作系统线程的标识的指令。
8 public static void FreeNamedDataSlot(string name)
为过程中的所有线程打消名称与槽之间的关联。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
9 public static Object GetData( LocalDataStoreSlot slot )
在以后线程的以后域中从以后线程上指定的槽中检索值。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
10 public static AppDomain GetDomain()
返回以后线程正在其中运行的以后域。
11 public static AppDomain GetDomainID()
返回惟一的应用程序域标识符。
12 public static LocalDataStoreSlot GetNamedDataSlot( string name )
查找已命名的数据槽。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
13 public void Interrupt()
中断处于 WaitSleepJoin 线程状态的线程。
14 public void Join()
在继续执行规范的 COM 和 SendMessage 音讯泵解决期间,阻塞调用线程,直到某个线程终止为止。此办法有不同的重载模式。
15 public static void MemoryBarrier()
按如下形式同步内存存取:执行以后线程的处理器在对指令从新排序时,不能采纳先执行 MemoryBarrier 调用之后的内存存取,再执行 MemoryBarrier 调用之前的内存存取的形式。
16 public static void ResetAbort()
勾销为以后线程申请的 Abort。
17 public static void SetData( LocalDataStoreSlot slot, Object data )
在以后正在运行的线程上为此线程的以后域在指定槽中设置数据。为了取得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。
18 public void Start()
开始一个线程。
19 public static void Sleep( int millisecondsTimeout )
让线程暂停一段时间。
20 public static void SpinWait( int iterations )
导致线程期待由 iterations 参数定义的工夫量。
21 public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address )
读取字段值。无论处理器的数目或处理器缓存的状态如何,该值都是由计算机的任何处理器写入的最新值。此办法有不同的重载模式。这里只给出了一些模式。
22 public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value )
立刻向字段写入一个值,以使该值对计算机中的所有处理器都可见。此办法有不同的重载模式。这里只给出了一些模式。
23 public static bool Yield()
导致调用线程执行筹备好在以后处理器上运行的另一个线程。由操作系统抉择要执行的线程。
创立线程
线程是通过扩大 Thread 类创立的。扩大的 Thread 类调用 Start() 办法来开始子线程的执行。
上面的程序演示了这个概念:
实例
using System;using System.Threading;namespace MultithreadingApplication{ class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); } static void Main(string[] args) { ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); Thread childThread = new Thread(childref); childThread.Start(); Console.ReadKey(); } }}
当下面的代码被编译和执行时,它会产生下列后果:
In Main: Creating the Child thread
Child thread starts