C#的多线程机制探索(二)—操纵一个线程

 
 任何程序在执行时,至少有一个主线程,下面这段小程序可以给读者一个直观的印象:
//SystemThread.cs
using System;
using System.Threading;

namespace ThreadTest
{
   class RunIt
   {
     [STAThread]
     static void Main(string[] args)
     {
       Thread.CurrentThread.Name="System Thread";// 给当前线程起名为 "System Thread"
Console.WriteLine(Thread.CurrentThread.Name+"'Status:"+Thread.CurrentThread.ThreadState);
       Console.ReadLine();
     }
   }
}

 编译执行后你看到了什么?是的,程序将产生如下输出:

System Thread's Status:Running


在这里,我们通过 Thread 类的静态属性 CurrentThread 获取了当前执行的线程,对其 Name 属性赋值 “System Thread” ,最后还输出了它的当前状态( ThreadState )。所谓静态属性,就是这个类所有对象所公有的属性,不管你创建了多少个这个类的实例,但是类的静态属性在内存中只有一个。很容易理解 CurrentThread 为什么是静态的 —— 虽然有多个线程同时存在,但是在某一个时刻, CPU 只能执行其中一个。

 就像上面程序所演示的,我们通过 Thread 类来创建和控制线程。注意到程序的头部,我们使用了如下命名空间:
using System;
using System.Threading;

 .net framework class library 中,所有与多线程机制应用相关的类都是放在 System.Threading 命名空间中的。其中提供 Thread 类用于创建线程, ThreadPool 类用于管理线程池等等,此外还提供解决了线程执行安排,死锁,线程间通讯等实际问题的机制。如果你想在你的应用程序中使用多线程,就必须包含这个类。 Thread 类有几个至关重要的方法,描述如下:
·                                 Start(): 启动线程
·                                 Sleep(int): 静态方法,暂停当前线程指定的毫秒数
·                                 Abort(): 通常使用该方法来终止一个线程
·                                 Suspend() :该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。
·                                 Resume(): 恢复被 Suspend() 方法挂起的线程的执行
 下面我们就动手来创建一个线程,使用 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;

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

 现在我们对怎样创建和控制一个线程已经有了一个初步的了解,下面我们将深入研究线程实现中比较典型的的问题,并且探讨其解决方法。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值