在TAP模式中,实现取消选项和之前的异步模式一样,都是使用CancellationToken
来实现,但是不同的是Task构造函数允许传入一个CancellationToken
,从而在任务实际启动之前取消它。
static void Main(string[] args) { var cts = new CancellationTokenSource(); // new Task时 可以传入一个 CancellationToken对象 可以在线程创建时 变取消任务
//传递两次Token,构造函数中传递Token的原因是任务执行前可能被取消 var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token); WriteLine(longTask.Status); cts.Cancel(); WriteLine(longTask.Status); WriteLine("第一个任务在运行前被取消."); // 同样的 可以通过CancellationToken对象 取消正在运行的任务 cts = new CancellationTokenSource(); longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token); longTask.Start(); for (int i = 0; i < 5; i++) { Sleep(TimeSpan.FromSeconds(0.5)); WriteLine(longTask.Status); } cts.Cancel(); for (int i = 0; i < 5; i++) { Sleep(TimeSpan.FromSeconds(0.5)); WriteLine(longTask.Status); } WriteLine($"这个任务已完成,结果为{longTask.Result}"); ReadLine(); } static int TaskMethod(string name, int seconds, CancellationToken token) { WriteLine($"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}"); for (int i = 0; i < seconds; i++) { Sleep(TimeSpan.FromSeconds(1)); if (token.IsCancellationRequested) { return -1; } } return 42 * seconds; }
运行结果如下图所示,这里需要注意的是,如果是在任务执行之前取消了任务,那么它的最终状态是Canceled
。如果是在执行过程中取消任务,那么它的状态是RanCompletion
。