接下来我们结合线程的ThreadState属性来了解线程的控制。ThreadState是一个枚举类型,它反映的是线程所处的状态。当一个Thread实例刚创建时,它的ThreadState是Unstarted;当此线程被调用Start()启动之后,它的ThreadState是 Running; 在此线程启动之后,如果想让它暂停(阻塞),可以调用Thread.Sleep() 方法,它有两个重载方法(Sleep(int )、Sleep(Timespan )),只不过是表示时间量的格式不同而已,当在某线程内调用此函数时,它表示此线程将阻塞一段时间(时间是由传递给 Sleep 的毫秒数或Timespan决定的,但若参数为0则表示挂起此线程以使其它线程能够执行,指定 Infinite 以无限期阻塞线程),此时它的ThreadState将变为WaitSleepJoin,另外值得注意一点的是Sleep()函数被定义为了static?! 这也意味着它不能和某个线程实例结合起来用,也即不存在类似于t1.Sleep(10)的调用!正是如此,Sleep()函数只能由需“Sleep”的线程自己调用,不允许其它线程调用,正如when to Sleep是个人私事不能由它人决定。但是当某线程处于WaitSleepJoin状态而又不得不唤醒它时,可使用Thread.Interrupt 方法 ,它将在线程上引发ThreadInterruptedException,下面我们先看一个例子(注意Sleep的调用方法):
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(Thread1));
t1.Start();
t1.Interrupt ();
E.WaitOne ();
t1.Interrupt ();
t1.Join();
Console.WriteLine(“t1 is end”);
}
static AutoResetEvent E = new AutoResetEvent(false);
public static void Thread1()
{
try
{//从参数可看出将导致休眠
Thread.Sleep(Timeout.Infinite);
}
catch(System.Threading.ThreadInterruptedException e)
{//中断处理程序
Console.WriteLine (" 1st interrupt");
}
E.Set ();
try
{// 休眠
Thread.Sleep(Timeout.Infinite );
}
catch(System.Threading.ThreadInterruptedException e)
{
Console.WriteLine (" 2nd interrupt");
}//暂停10秒
Thread.Sleep (10000);
}
运行结果为:
1st interrupt
2nd interrupt
(10s后)t1 is end
从上例我们可以看出Thread.Interrupt方法可以把程序从某个阻塞(WaitSleepJoin)状态唤醒进入对应的中断处理程序,然后继续往下执行(它的ThreadState也变为Running),此函数的使用必须注意以下几点:
1、此方法不仅可唤醒由Sleep导致的阻塞,而且对一切可导致线程进入WaitSleepJoin状态的方法(如Wait和Join)都有效。如上例所示, 使用时要把导致线程阻塞的方法放入try块内, 并把相应的中断处理程序放入catch块内。
2、对某一线程调用Interrupt, 如它正处于WaitSleepJoin状态, 则进入相应的中断处理程序执行, 若此时它不处于WaitSleepJoin状态, 则它后来进入此状态时, 将被立即中断。若在中断前调用几次Interrupt, 只有第一次调用有效, 这正是上例我用同步的原因, 这样才能确保第二次调用Interrupt在第一个中断后调用,否则的话可能导致第二次调用无效(若它在第一个中断前调用)。你可以把同步去掉试试,其结果很可能是: 1st interrupt










