三种方式
- 通过使用轮循操作来检查IsCancellationRequested是否为true,是则需要取消当前操作过程(直接使用return)
- 通过抛出一个OperationCanceledException异常来终止操作(操作之外的代码控制取消过程)
- 注册一个回调函数(操作取消时,线程池将调用该函数)
static void Main(string[] args) { using (var cts = new CancellationTokenSource()) { CancellationToken token = cts.Token; ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token)); Thread.Sleep(TimeSpan.FromSeconds(2)); cts.Cancel();//传达取消请求 } using (var cts = new CancellationTokenSource()) { CancellationToken token = cts.Token; ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token)); Thread.Sleep(TimeSpan.FromSeconds(2)); cts.Cancel();//传达取消请求 } using (var cts = new CancellationTokenSource()) { CancellationToken token = cts.Token; ThreadPool.QueueUserWorkItem(_ => AsyncOperation3(token)); Thread.Sleep(TimeSpan.FromSeconds(2)); cts.Cancel();//传达取消请求 } Thread.Sleep(TimeSpan.FromSeconds(2)); } static void AsyncOperation1(CancellationToken token) { Console.WriteLine("Starting the first task"); //使用轮循操作来检查IsCancellationRequested是否为true,是则需要取消当前操作过程 for (int i = 0; i < 5; i++) { if (token.IsCancellationRequested)//获取是否已请求取消此标记。 { Console.WriteLine("The first task has been canceled."); return;//返回return取消操作 } Thread.Sleep(TimeSpan.FromSeconds(1)); } Console.WriteLine("The first task has completed succesfully"); } static void AsyncOperation2(CancellationToken token) { try { Console.WriteLine("Starting the second task"); for (int i = 0; i < 5; i++) { token.ThrowIfCancellationRequested();//如果已请求取消此标记,则引发 System.OperationCanceledException。 Thread.Sleep(TimeSpan.FromSeconds(1)); } Console.WriteLine("The second task has completed succesfully"); } catch (OperationCanceledException) { Console.WriteLine("The second task has been canceled."); } } private static void AsyncOperation3(CancellationToken token) { bool cancellationFlag = false; token.Register(() => cancellationFlag = true);//注册一个回调函数,当操作取消时,线程池将调用该回调函数 Console.WriteLine("Starting the third task"); for (int i = 0; i < 5; i++) { if (cancellationFlag) { Console.WriteLine("The third task has been canceled."); return; } Thread.Sleep(TimeSpan.FromSeconds(1)); } Console.WriteLine("The third task has completed succesfully"); }
工作原理:
本节中介绍了CancellationTokenSource和CancellationToken两个新类。他们在.NET4.0被引入,目前是实现异步操作的取消操作的事实标准。由于线程池已经存在了很长时间,并没有特殊的API来实现取消标记功能,但是仍然可以对线程池使用上述API。
在本程序中使用了三种方式来实现取消过程。第一个是轮询来检查CancellationToken.IsCancellationRequested属性。如果该属性为true,则说明操作需要被取消,我们必须放弃该操作。
第二种方式是跑出一个OperationCanceledException异常。这允许在操作之外控制取消过程,即需要取消操作时,通过操作之外的代码来处理。
最后一种方式是注册一个回调函数。当操作被取消时。,在线程池将调用该回调函数。这允许链式传递一个取消逻辑到另一个异步操作中。