近来在学习Eugene Agafonov编写的《C#多线程编程实战》(译),做些笔记也顺便分享一下^-^
using System; using System.Threading; namespace 线程池中取消异步操作 { class Program { 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)); Console.ReadKey(); } static void AsyncOperation1(CancellationToken token) { Console.WriteLine("Starting the first task"); for (int i = 0; i < 5; i++) { if (token.IsCancellationRequested) { Console.WriteLine("The first task has been canceled."); 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(); Thread.Sleep(TimeSpan.FromSeconds(1)); } Console.WriteLine("The second task has completed successfully"); } 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 successfully"); } } }
这里引入了两个类CancellationToken和CancellationTokenSource,是实现异步操作的取消操作的事实标准。
程序里一共使用了三种方式来实现取消过程:1、通过轮询来检查CancellationToken.IsCancellationRequested属性,如果该属性为true,则说明操作需要被取消,我们必须放弃该操作。
2、抛出一个OperationCanceledException异常,这允许在操作之外控制取消过程,即需要取消操作时,通过操作之外的代码来处理。
3、注册一个回调函数,当操作被取消时,在线程池将调用该回调函数,这允许链式传递一个取消逻辑到另一个异步操作中。