C#的多线程机制探索(2)

下面我们就动手来创建一个线程,使用 Thread 类创建线程时,只需提供线程入口即可。线程入口使程序知道该让这个线程干什么事,在 C# 中,线程入口是通过 ThreadStart 代理( delegate )来提供的,你可以把 ThreadStart 理解为一个函数指针,指向线程要执行的函数,当调用 Thread.Start() 方法后,线程就开始执行 ThreadStart 所代表或者说指向的函数。

 打开你的 VS.net ,新建一个控制台应用程序( Console Application ),下面这些代码将让你体味到完全控制一个线程的无穷乐趣!
//ThreadTest.cs

using System;
using System.Threading;

namespace ThreadTest
{
   public class Alpha
     {
       public void Beta()
       {
         while (true)
         {
           Console.WriteLine("Alpha.Beta is running in its own thread.");
         }
       }
     };

     public class Simple
     {
       public static int Main()
       {
         Console.WriteLine("Thread Start/Stop/Join Sample");

         Alpha oAlpha = new Alpha();
         file:// 这里创建一个线程,使之执行 Alpha 类的 Beta() 方法
         Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
         oThread.Start();
         while (!oThread.IsAlive);
         Thread.Sleep(1);
         oThread.Abort();
         oThread.Join();
         Console.WriteLine();
         Console.WriteLine("Alpha.Beta has finished");
         try
         {
           Console.WriteLine("Try to restart the Alpha.Beta thread");
           oThread.Start();
         }
         catch (ThreadStateException)
         {
           Console.Write("ThreadStateException trying to restart Alpha.Beta. ");
           Console.WriteLine("Expected since aborted threads cannot be restarted.");
           Console.ReadLine();
         }
         return 0;
       }
     }
   }

 这段程序包含两个类 Alpha Simple ,在创建线程 oThread 时我们用指向 Alpha.Beta() 方法的初始化了 ThreadStart 代理( delegate )对象,当我们创建的线程 oThread 调用 oThread.Start() 方法启动时,实际上程序运行的是 Alpha.Beta() 方法:
Alpha oAlpha = new Alpha();
   Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
   oThread.Start();

 然后在 Main() 函数的 while 循环中,我们使用静态方法 Thread.Sleep() 让主线程停了 1ms ,这段时间 CPU 转向执行线程 oThread 。然后我们试图用 Thread.Abort() 方法终止线程 oThread ,注意后面的 oThread.Join() Thread.Join() 方法使主线程等待,直到 oThread 线程结束。你可以给 Thread.Join() 方法指定一个 int 型的参数作为等待的最长时间。之后,我们试图用 Thread.Start() 方法重新启动线程 oThread ,但是显然 Abort() 方法带来的后果是不可恢复的终止线程,所以最后程序会抛出 ThreadStateException 异常。

 程序最后得到的结果将如下图:


 
在这里我们要注意的是其它线程都是依附于 Main() 函数所在的线程的, Main() 函数是 C# 程序的入口,起始线程可以称之为主线程,如果所有的前台线程都停止了,那么主线程可以终止,而所有的后台线程都将无条件终止。而所有的线程虽然在微观上是串行执行的,但是在宏观上你完全可以认为它们在并行执行。

 读者一定注意到了 Thread.ThreadState 这个属性,这个属性代表了线程运行时状态,在不同的情况下有不同的值,于是我们有时候可以通过对该值的判断来设计程序流程。 ThreadState 在各种情况下的可能取值如下:
  • Aborted:线程已停止
  • AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止
  • Background:线程在后台执行,与属性Thread.IsBackground有关
  • Running:线程正在正常运行
  • Stopped:线程已经被停止
  • StopRequested:线程正在被要求停止
  • Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行)
  • SuspendRequested:线程正在要求被挂起,但是未来得及响应
  • Unstarted:未调用Thread.Start()开始线程的运行
  • WaitSleepJoin:线程因为调用了Wait(),Sleep()Join()等方法处于封锁状态
 上面提到了 Background 状态表示该线程在后台运行,那么后台运行的线程有什么特别的地方呢?其实后台线程跟前台线程只有一个区别,那就是后台线程不妨碍程序的终止。一旦一个进程所有的前台线程都终止后, CLR (通用语言运行环境)将通过调用任意一个存活中的后台进程的 Abort() 方法来彻底终止进程。

 当线程之间争夺 CPU 时间时, CPU 按照是线程的优先级给予服务的。在 C# 应用程序中,用户可以设定 5 个不同的优先级,由高到低分别是 Highest AboveNormal Normal BelowNormal Lowest ,在创建线程时如果不指定优先级,那么系统默认为 ThreadPriority.Normal 。给一个线程指定优先级
,我们可以使用如下代码:
// 设定优先级为最低
myThread.Priority=ThreadPriority.Lowest;

 通过设定线程的优先级,我们可以安排一些相对重要的线程优先执行,例如对用户的响应等等。

 现在我们对怎样创建和控制一个线程已经有了一个初步的了解,下面我们将深入研究线程实现中比较典型的的问题,并且探讨其解决方法。

你可能感兴趣的:(C#,Asp.net)