C#多线程编程笔记(4.3)-Task任务中实现取消选项

近来在学习Eugene Agafonov编写的《C#多线程编程实战》(译),做些笔记也顺便分享一下^-^ 

using System;
using System.Threading.Tasks;
using System.Threading;
 
namespace 实现取消选项
{
    class Program
    {
        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token);
            Console.WriteLine(longTask.Status);
            cts.Cancel();
            Console.WriteLine(longTask.Status);
            Console.WriteLine("First task has been cancelled before execution");
 
            cts = new CancellationTokenSource();
            longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token);
            longTask.Start();
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
                Console.WriteLine(longTask.Status);
            }
            cts.Cancel();
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
                Console.WriteLine(longTask.Status);
            }
            Console.WriteLine("A task has been completed with result {0}.", longTask.Result);
            Console.ReadKey();
        }
        private static int TaskMethod(string name,int seconds,CancellationToken token)
        {
            Console.WriteLine("Task {0} is running on a thread id {1},Is thread pool thread: {2}",
                               name, Thread.CurrentThread.ManagedThreadId,
                               Thread.CurrentThread.IsThreadPoolThread);
            for (int i = 0; i < seconds; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));
                if (token.IsCancellationRequested)
                {
                    return -1;
                }
            }
            return 42 * seconds;
        }
    }
}

程序运行结果如下:


在我之前的博客里讨论过取消标志的概念,而本例又是一个关于为TPL任务实现取消选项的简单例子。

首先看longTask的创建代码。我们将给底层任务传递一次取消标志,然后给任务构造函数再传递一次。为什么需要提供取消标志两次呢?

答案是如果再任务实际启动前取消它,该任务的TPL基础设施有责任处理该取消操作,因为这些代码根本不会执行。通过得到的第一个任务的状态可以知道它被取消了。如果尝试对该任务调用Start方法,将会得到InvalidOperationException异常。

然后需要自己写代码来处理取消过程。这意味着我们对取消过程全权负责,并且在取消任务后,任务的状态仍然是RanToCompletion,因为从TPL的视角来看,该任务正常完成了它的工作。

猜你喜欢

转载自blog.csdn.net/qq_35445058/article/details/80829339