C#线程从陌生到熟悉(2)
首先我们来看看线程的状态
线程状态
表1-1 ThreadState定义的枚举常数
成员名称 |
说 明 |
Aborted |
线程处于Stopped状态中 |
AbortRequested |
已对线程调用了Thread.Abort方法,但线程尚未收到试图终止它的挂起的System.Threading. ThreadAbortException |
Background |
线程正作为后台线程执行(相对于前台线程而言)。此状态可以通过设置Thread.IsBackground属性来控制 |
Running |
线程已启动,它未被阻塞,并且没有挂起的ThreadAbortException |
Stopped |
线程已停止 |
StopRequested |
正在请求线程停止。这仅用于内部 |
Suspended |
线程已挂起 |
SuspendRequested |
正在请求线程挂起 |
Unstarted |
尚未对线程调用Thread.Start方法 |
WaitSleepJoin |
由于调用Wait、Sleep或Join,线程已被阻止 |
Thread对象的ThreadState属性提供一个由ThreadState定义的位掩码,它指示线程的当前状态。一个线程至少总是处于ThreadState枚举中定义的一个可能状态,并且可以同时处于多个状态。
注意,只能在一些调试方案中使用线程状态,而不应该在代码中使用线程状态来同步线程活动。
在创建托管线程时,该线程处于Unstarted状态。线程会保持Unstarted状态,直到被操作系统调度到已启动状态。调用Start方法使操作系统知道该线程可启动,但是它并不直接更改线程的状态。一旦线程处于已启动的状态中,就可以执行许多操作来使线程更改状态。表1-2列出了使状态发生更改的操作,以及相应的新状态。
表1-2 使线程状态发生更改的操作及相应的新状态
操 作 |
ThreadState |
在公共语言运行库中创建线程 |
Unstarted |
线程调用Start |
Unstarted |
线程开始运行 |
Running |
续表
操 作 |
ThreadState |
线程调用Sleep |
WaitSleepJoin |
线程对其他对象调用Wait |
WaitSleepJoin |
线程对其他线程调用Join |
WaitSleepJoin |
另一个线程调用Interrupt |
Running |
另一个线程调用Suspend |
SuspendRequested |
线程响应Suspend请求 |
Suspended |
另一个线程调用Resume |
Running |
另一个线程调用Abort |
AbortRequested |
线程响应Abort请求 |
Stopped |
线程被终止 |
Stopped |
Abort方法,调用该方法后,在当前线程中引发一个ThreadAbortException异常,该异常导致线程死亡!线程进入Stopped状态,不能在重启!
请看下面的例子
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication4 { class Program { static void Main(string[] args) { Thread t1 = new Thread(Print); // t1.Abort();引发ThreadAbortException异常 t1.Start(); // t1.Abort(); //t1.Join();阻塞调用线程,直到某个线程终止时为止。 Console.WriteLine("主线程被调用"); // t1.Start();引发ThreadAbortException异常无法重新启动 } static void Print() { Thread.Sleep(2000); Console.WriteLine("线程被调用!"); } } }
从这个例子中,我们可以看出,线程处于Unstarted状态时,调用Abort()方法时,将引发异常!
将第二个注释打开,得到如下结果
线程被终止了!把第四个注释打开,又会引发异常!
在这里我要说明下Join()这个方法,将第三个注释打开,会得到如下结果,
Join这个方法的作用是阻塞调用他的线程,换句话说就是调用他的线程处于阻塞状态,直到这个线程执行结束,调用他的线程才继续执行!这里调用他的线程指的是主线程!
Interrupt 该方法打断一个处于WaitSleepJoin状态的线程。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { Thread t1 = new Thread(Print); t1.Start(); Thread.Sleep(500); t1.Interrupt(); Thread.Sleep(500); Console.WriteLine("主线执行结束!"); } static void Print() { try { Thread t2=new Thread(Print2); t2.Start(); t2.Join(); } catch (Exception e) { Console.WriteLine("捕获到异常:{0}", e.ToString()); } Console.WriteLine("线程1运行!"); } static void Print2() { Thread.Sleep(2000); Console.WriteLine("线程2运行!"); } } }
运行结果为
从中可以看出线程1调同线程2的方法时被打断了,以致于线程1直接运行了!这个就是Interrupt得作用!如果将Interrupt这个方法给注释掉,那就会看到线程2运行完了,线程1才继续运行!Interrupt 该方法打断一个处于WaitSleepJoin状态的线程。应该可以理解了吧!
好了,这次就到这里了!