Csharp 简明教程

C

thread 定义为程序的执行路径。每个线程定义一个唯一的控制流。如果你的应用程序涉及复杂且耗时的操作,那么设置不同的执行路径或线程通常会有所帮助,每个线程执行特定作业。

线程是 lightweight processes 。现代操作系统在实现并行编程时使用的线程是一个常见的示例。使用线程可以节省CPU周期的浪费并提高应用程序的效率。

到目前为止,我们编写的程序是单个线程作为单个进程运行,这是应用程序的运行实例。然而,通过这种方式,应用程序一次只能执行一项工作。为了使它一次执行多项任务,可以将其划分为更小的线程。

Thread Life Cycle

线程的生命周期从创建System.Threading.Thread类的对象时开始,并在线程终止或完成执行时结束。

以下是线程生命周期中的各种状态 -

  1. Value parameters - 这是当创建线程实例但未调用Start方法时的状态。

  2. The Ready State − 当线程已准备好运行并等待 CPU 周期时,会出现此情况。

  3. The Not Runnable State − 线程不可执行,当调用 Sleep 方法、调用 Wait 方法、被 I/O 操作阻塞时。

  4. The Dead State − 当线程完成执行或被中止时,会出现此情况。

The Main Thread

在 C# 中, System.Threading.Thread 类用于处理线程。它允许在多线程应用程序中创建和访问各个线程。进程中要执行的第一个线程称为 main 线程。

当 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

Properties and Methods of the Thread Class

下表显示了 Thread 类的部分常用 properties

Sr.No.

Property & Description

1

CurrentContext 获取线程正在执行的当前上下文。

2

CurrentCulture 获取或设置当前线程的区域性。

3

CurrentPrinciple 获取或设置线程的当前委托(用于基于角色的安全性)。

4

CurrentThread 获取当前正在运行的线程。

5

CurrentUICulture 获取或设置 ResourceManager 用于在运行时查找特定于区域性的资源的当前区域性。

6

ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的的信息。

7

IsAlive 获取一个值,该值指示当前线程的执行状态。

8

IsBackground 获取或设置一个值,该值指示线程是否为后台线程。

9

IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。

10

ManagedThreadId 获取当前托管线程的唯一标识符。

11

Name 获取或设置线程的名称。

12

Priority 获取或设置一个值,该值指示线程的调度优先级。

13

ThreadState 获取一个值,其中包含当前线程的状态。

下表显示了 Thread 类中经常使用的一些 methods

Sr.No.

Method & Description

1

public void Abort() 引发 Thread 所调用的线程中的 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() 使调用线程向准备在当前处理器上运行的另一个线程提交执行。操作系统将选择要提交的线程。

Creating Threads

通过扩展 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

Managing Threads

Thread 类提供了各种用于管理线程的方法。

以下示例演示如何使用 sleep() 方法使线程暂停一段时间。

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");

         // the thread is paused for 5000 milliseconds
         int sleepfor = 5000;

         Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
         Thread.Sleep(sleepfor);
         Console.WriteLine("Child thread resumes");
      }

      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
Child Thread Paused for 5 seconds
Child thread resumes

Destroying Threads

Abort() 方法用于销毁线程。

运行时将导致一个 ThreadAbortException 。此异常无法被捕获,控制权将(如果有的话)发送到 finally 块。

以下程序说明了这一点 −

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         try {
            Console.WriteLine("Child thread starts");

            // do some work, like counting to 10
            for (int counter = 0; counter <= 10; counter++) {
               Thread.Sleep(500);
               Console.WriteLine(counter);
            }

            Console.WriteLine("Child Thread Completed");
         } catch (ThreadAbortException e) {
            Console.WriteLine("Thread Abort Exception");
         } finally {
            Console.WriteLine("Couldn't catch the Thread Exception");
         }
      }
      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();

         //stop the main thread for some time
         Thread.Sleep(2000);

         //now abort the child
         Console.WriteLine("In Main: Aborting the Child thread");

         childThread.Abort();
         Console.ReadKey();
      }
   }
}

编译并执行上述代码后,将产生以下结果 −

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception