C# Tip -- 如何优雅的控制线程状态

先问读者一个问题,如果想控制一个线程(Thread)挂起,继续,结束你会优先选择如何处理?

从面试的经验来看,多数的面试者都会说Thread不是提供了Suspend,Resume,Abort等方法吗,直接调用就好了,简单快捷.但很多情况下简单就是美只是一个谎言而已.

Suspend和Resume方法已经被MS标注过时(Obsolete),不建议用户使用,MS同时推荐通过同步控制来管理线程状态.

 

再问读者一个问题,如果控制一个线程池中的线程的挂起,继续,结束你会优先选择如何处理?

也许有人会说,既然没法用API了,那我定义一些标志量,来做状态控制不就可以了吗?

确实,说起来很简单.那么变量的值需不需要考虑由于多线程问题导致的读写问题呢,你会怎么处理?

如果不用标志量,可以用同步事件来做,会不会跟优雅一些呢?

 

让我把传统的方式以及使用同步方式做的控制都写一遍,让读者来做取舍吧.

 

代码如下,注释也比较全,就不再累述细节.

 

class Program { static void Main(string[] args) { UseThreadAPI(); UseSyncEvent(); UseThreadPool(); UseSyncEventThreadPool(); Console.WriteLine("All tests finished"); Console.ReadKey(); } ///

/// 使用标准Thread API来控制线程状态, /// Suspend和Resume是过时的方法,MS不推荐使用 /// MS推荐的方式就是后面要提到的使用Monitor,Event等做同步控制. /// static void UseThreadAPI() { Console.WriteLine("----------Use thread API----------"); Thread t = new Thread( new ThreadStart(() => { while (true) { Console.WriteLine("Now Date:{0}", DateTime.Now); Thread.Sleep(1000); } } )); t.Start(); //暂停线程执行 Console.ReadKey(); t.Suspend(); Console.WriteLine("Thread suspended"); //继续线程执行 Console.ReadKey(); t.Resume(); Console.WriteLine("Thread resumed"); //结束线程 Console.ReadKey(); t.Abort(); Console.WriteLine("Thread aborted"); Console.ReadKey(); } /// /// 使用Event做同步控制 /// 三个Event组合使用就可以产生同Suspend,Resuem,Abort相同的效果 /// 而且你可以控制Abort的时机以及并作出适当的处理 /// 而不是像Thread.Abort一样通过异常的方式结束线程 /// static void UseSyncEvent() { Console.WriteLine("----------Use sync event----------"); AutoResetEvent evtPause = new AutoResetEvent(false); AutoResetEvent evtResume = new AutoResetEvent(false); AutoResetEvent evtStop = new AutoResetEvent(false); Thread t = new Thread( new ThreadStart(() => { //WaitOne(1000),可产生Sleep(1000)相同的效果 //如果eveStop被置位,则立即返回True,跳出循环 //如果等待1000ms超时,则返回False,继续循环 while (!evtStop.WaitOne(1000)) { //WaitOne(0)可立即判断evtPase有没有被置位 //如果置位,进入暂停状态,等待Resume被置位才会恢复线程执行 if (evtPause.WaitOne(0)) { //WaitOne()不带参数表示一直等待,直到被置位 evtResume.WaitOne(); } Console.WriteLine("Now Date:{0}", DateTime.Now); } } )); t.Start(); //暂停线程执行 Console.ReadKey(); evtPause.Set(); Console.WriteLine("Thread suspended"); //继续线程执行 Console.ReadKey(); evtResume.Set(); Console.WriteLine("Thread resumed"); //结束线程 Console.ReadKey(); evtStop.Set(); Console.WriteLine("Thread stopped"); Console.ReadKey(); } class ThreadStatusController { /// /// 声明为volatile可以避免用lock进行加锁同步 /// 编译器自己会做优化 /// 另外不能声明属性为volatile,因此只能作为成员变量放出. /// public volatile bool IsPauseRequired; public volatile bool IsStopRequired; } /// /// 对于放入线程池的进程,是无法通过Thread的API进行控制的 /// 通常的做法是通过一些bool量做控制,这不是优雅的解决方案. /// static void UseThreadPool() { Console.WriteLine("----------Use thread pool----------"); var tsc = new ThreadStatusController(); ThreadPool.QueueUserWorkItem(status => { var ctrl = status as ThreadStatusController; //等待IsStopRequired标志量的值为True while (!ctrl.IsStopRequired) { //如果不是Pause请求,则执行 if (!ctrl.IsPauseRequired) Console.WriteLine("Now Date:{0}", DateTime.Now); Thread.Sleep(1000); } }, tsc); //暂停线程执行 Console.ReadKey(); tsc.IsPauseRequired = true; Console.WriteLine("Thread suspended"); //继续线程执行 Console.ReadKey(); tsc.IsPauseRequired = false; Console.WriteLine("Thread resumed"); //结束线程 Console.ReadKey(); tsc.IsStopRequired = true; Console.WriteLine("Thread aborted"); Console.ReadKey(); } /// /// 声明三个同步事件分别对应三种同步状态 /// class ThreadStatusEventController { public ThreadStatusEventController() { PauseEvent = new AutoResetEvent(false); ResumeEvent = new AutoResetEvent(false); StopEvent = new AutoResetEvent(false); } public AutoResetEvent PauseEvent { get; set; } public AutoResetEvent ResumeEvent { get; set; } public AutoResetEvent StopEvent { get; set; } } static void UseSyncEventThreadPool() { Console.WriteLine("----------Use sync event with thread pool----------"); var tsc = new ThreadStatusEventController(); ThreadPool.QueueUserWorkItem(status => { var ctrl = status as ThreadStatusEventController; //控制代码跟采用Thread的方式类似,不累述 while (!ctrl.StopEvent.WaitOne(1000)) { if (ctrl.PauseEvent.WaitOne(0)) { ctrl.ResumeEvent.WaitOne(); } Console.WriteLine("Now Date:{0}", DateTime.Now); } }, tsc); //暂停线程执行 Console.ReadKey(); tsc.PauseEvent.Set(); Console.WriteLine("Thread suspended"); //继续线程执行 Console.ReadKey(); tsc.ResumeEvent.Set(); Console.WriteLine("Thread resumed"); //结束线程 Console.ReadKey(); tsc.StopEvent.Set(); Console.WriteLine("Thread aborted"); Console.ReadKey(); } }

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(C#)