在多线程编程中线程池是不得不提的,在.net4.0之前一般对于线程池的说法是,把需要的线程交给线程池,我们自己将更多的关注点放在业务上,个人认为这既是线程池的优点也是缺点---加入线程池之后人为无法控制,也没有内在的方法告知线程的执行结果。
今天早晨拜读了Jeffrey的著作26th章。根据自己的理解今天主要学习“如何取消线程池中的线程”。
首先介绍System.Thread命名空间下面的两个类:
- CancellationToken ,其实这是一个结构,它主要传播有关应取消操作的通知。
- CancellationTokenSource ,这是一个类,它的主要作用是操作(取消)与之相关联的线程,然后通知CancellationToken其对应的操作被取消。
CancellationTokenSource主要介绍一个方法和两个属性:
- Token,这个属性获取与CancellationTokenSource相关联的CancellationToken。
- IsCancellationRequested,这个属性返回是否已经执行取消操作。
- Cancel,这是一个方法,是用于执行取消动作
- 详细参数可以查看具体函数
CancellationToken介绍一个方法和一个属性
- Register方法,用于注册一个在取消当前CancellationToken时执行的委托
- IsCancellationRequested,主要用于显示对于当前的CancellationToken,取消是否执行
- 详细参数可以查看具体函数
基于上面的介绍实现一个例子,把Jeffrey先生的例子稍作修改:
代码
namespace CancellationStudy { internal class CancellationDemo { public static void Main() { System.Threading.CancellationTokenSource cts =
new CancellationTokenSource(); //将CancellationToken传递给相应的操作 ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000)); ThreadPool.QueueUserWorkItem(o => Count2(cts.Token, 1000));
Console.WriteLine("Please <Enter> to cancel the operation."); Console.ReadLine(); cts.Cancel(); Console.ReadLine(); }
private static void Count(CancellationToken token, int countTo) { for (int count = 0; count < countTo; count++) { //这个IsCancellationRequested是CancellationToken的属性 //主要用于显示对于当前的token,取消是否执行 if (token.IsCancellationRequested) { Console.WriteLine("Count is cancelled"); break; } Console.WriteLine(count); Thread.Sleep(200); } Console.WriteLine("count is done"); }
private static void Count2(CancellationToken token, int countTo) { for (int count = 0; count < countTo; count++) { if (token.IsCancellationRequested) { Console.WriteLine("Count2 is cancelled"); break; } Console.WriteLine(count); Thread.Sleep(200); } Console.WriteLine("count2 is done"); } } }
Console.WriteLine("Please <Enter> to cancel the operation."); Console.ReadLine(); cts.Cancel(); Console.ReadLine(); }
private static void Count(CancellationToken token, int countTo) { for (int count = 0; count < countTo; count++) { //这个IsCancellationRequested是CancellationToken的属性 //主要用于显示对于当前的token,取消是否执行 if (token.IsCancellationRequested) { Console.WriteLine("Count is cancelled"); break; } Console.WriteLine(count); Thread.Sleep(200); } Console.WriteLine("count is done"); }
private static void Count2(CancellationToken token, int countTo) { for (int count = 0; count < countTo; count++) { if (token.IsCancellationRequested) { Console.WriteLine("Count2 is cancelled"); break; } Console.WriteLine(count); Thread.Sleep(200); } Console.WriteLine("count2 is done"); } } }
可以在取消的时候执行任意自己想要的方法,这时CancellationToken的Register方法就派上用场了。
代码
public static void Main() { RegisterMoreOperations(); }
public static void RegisterMoreOperations() { var cts1 = new CancellationTokenSource(); cts1.Token.Register(() => Console.WriteLine("cts1 Canceled 1")); cts1.Token.Register(() => Console.WriteLine("cts1 Canceled 2")); cts1.Cancel(); Console.WriteLine("cts1 cancel="+cts1.IsCancellationRequested); var cts2 = new CancellationTokenSource(); cts2.Token.Register(() => Console.WriteLine("cts2 Canceled 1")); Console.WriteLine("cts2 cancel=" + cts2.IsCancellationRequested); }
public static void RegisterMoreOperations() { var cts1 = new CancellationTokenSource(); cts1.Token.Register(() => Console.WriteLine("cts1 Canceled 1")); cts1.Token.Register(() => Console.WriteLine("cts1 Canceled 2")); cts1.Cancel(); Console.WriteLine("cts1 cancel="+cts1.IsCancellationRequested); var cts2 = new CancellationTokenSource(); cts2.Token.Register(() => Console.WriteLine("cts2 Canceled 1")); Console.WriteLine("cts2 cancel=" + cts2.IsCancellationRequested); }
上面是我自己的理解,不是很深,如果有人看到,还望指点。本人非常感谢!!!!!!
本文在刚开始的时候提到线程池没有内在的方法告知线程的执行结果。在.net4.0中引进了Task的概念,它完全可以做到此功能。改日再学,今天得就寝了。