Parallel World 4 – Parallel Task (1)

I. 概述

在.NET Framework 4之前,如果我们要使用多核或者多CPU的优势,我们需要使用多线程的方式(大家感兴趣可以参考我的另一篇关于线程方面的文章)。在.NET Framework 4中,微软提供了一个新的命名空间System.Threading.Tasks来实现并行,通常被称为TPL。TPL引入了一种新的基于task的编程模型,我们使用它可以很轻松的实现并行,使开发人员从跟底层的Thread打交道的方式解放出来。但是注意task并没有取代thread, 而实际上task是基于thread的,这一系列文章之后我会写一篇关于二者之间关系的文章。

II. 创建和启动Task

   1: static void Main(string[] args)
   2: {
   3:  
   4:     //Action
   5:     Task task1 = new Task(new Action(CubicSum));
   6:     //Anonymous Method
   7:     Task task2 = new Task(delegate { CubicSum(); });
   8:     //Lambda Expression and a named method
   9:     Task task3 = new Task(() => CubicSum());
  10:     //Lambda Expression and an anonymous method
  11:     Task task4 = new Task(() => { CubicSum(); });
  12:  
  13:     task1.Start();
  14:     task2.Start();
  15:     task3.Start();
  16:     task4.Start();
  17:  
  18:     Console.ReadLine();
  19: }

在上述代码中,我们使用了多种方式,大家可以自己尝试一下。是不是创建和启动一个task很容易。注意,要引入System.Threading.Tasks。

在创建Task的时候,我们还可以通过TaskCreationOptions枚举为它设置一些选项。

None Task将采用默认行为
AttachedToParent Task将依附于它的父Task
LongRunning Task将长时间运行
PreferFairness 请求Task Schedule使这个task尽量“公平”地运行

III. 获得Task执行后的返回结果

可以使用Task<TResult>来获得Task执行后的返回结果。我们改写QuadraticSum()方法,让它可以返回值。

   1: private static double QuadraticSum()
   2: {
   3:     double sum = 0;
   4:     var sw = Stopwatch.StartNew();
   5:     for (int i = 0; i < NUM_MAX; i++)
   6:     {
   7:         sum = sum + (2 * i + 1) * (i + 1) * i / 6;
   8:     }
   9:  
  10:     return sum;
  11: }
  12:  
  13:  
  14: static void Main(string[] args)
  15: {
  16:  
  17:     Task<double> task1 = new Task<double>(() => QuadraticSum());
  18:  
  19:     task1.Start();
  20:  
  21:     Console.WriteLine("Result is: {0}",task1.Result);
  22:  
  23:     Console.ReadLine();
  24: }

IV. 取消Task

   1: private const int NUM_MAX = 100000000;
   2:  
   3: static void Main(string[] args)
   4: {
   5:     //create a CancellationTokenSource
   6:     CancellationTokenSource tokenSource = new CancellationTokenSource();
   7:  
   8:     //create a CancellationToken via CancellationTokenSource
   9:     CancellationToken token = tokenSource.Token;
  10:  
  11:     //create a Task with a CancellationToken
  12:     Task task1 = new Task(() =>
  13:     {
  14:         double sum = 0;
  15:         for (int i = 0; i < NUM_MAX; i++)
  16:         {
  17:             sum = sum + (2 * i + 1) * (i + 1) * i / 6;
  18:         }
  19:     },token);
  20:  
  21:     task1.Start();
  22:  
  23:     Console.WriteLine("Cancelling task");
  24:     //cancel the task
  25:     tokenSource.Cancel();
  26:  
  27:     Console.ReadLine();
  28: }

1. 通过上述代码我们可以看到如何Cancel一个Task的基本步骤:

第一步:创建一个CancellationTokenSource

第二步:创建一个CancellationToken

第三步:把CancellationToken作为一个参数,传递到Task中

第四步:调用CancellationTokenSource的Cancel()方法

当然我们也可以取消多个Task:只要把CancellationToken作为一个参数,传递到每一个Task中,然后当系统调用CancellationTokenSource的Cancel()方法时,就可以取消所有使用CancellationToken的Task, 当然这些Task要使用同一个CancellationToken

2. 使用连接CancellationToken类取消Task

我们可以使用System.Threading.CancellationTokenSource.CreateLinkedTokenSource()来连接多个CancellationTokenSource,只要其中一个调用CancellationTokenSource的Cancel()方法,所有使用这个连接CancellationTokenSource的Task都会被取消。

   1: private const int NUM_MAX = 100000000;
   2:  
   3: static void Main(string[] args)
   4: {
   5:  
   6:     //create multipule CancellationTokenSources
   7:     CancellationTokenSource tokenSource1 = new CancellationTokenSource();
   8:     CancellationTokenSource tokenSource2 = new CancellationTokenSource();
   9:     CancellationTokenSource tokenSource3 = new CancellationTokenSource();
  10:  
  11:     //linked these multipule CancellationTokenSources
  12:     CancellationTokenSource LinkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource1.Token, tokenSource2.Token, tokenSource3.Token);
  13:  
  14:     //create a CancellationToken via linked CancellationTokenSource
  15:     CancellationToken token = LinkedTokenSource.Token;
  16:  
  17:     //create a Task with a CancellationToken
  18:     Task task1 = new Task(() =>
  19:     {
  20:         double sum = 0;
  21:         for (int i = 0; i < NUM_MAX; i++)
  22:         {
  23:             sum = sum + (2 * i + 1) * (i + 1) * i / 6;
  24:         }
  25:     }, token);
  26:  
  27:     //create a Task with a CancellationToken
  28:     Task task2 = new Task(() =>
  29:     {
  30:         double sum = 0;
  31:         for (int i = 0; i < NUM_MAX; i++)
  32:         {
  33:             sum = sum + (2 * i + 1) * (i + 1) * i / 6;
  34:         }
  35:     }, token);
  36:  
  37:     task1.Start();
  38:     task2.Start();
  39:  
  40:     Console.WriteLine("Cancelling all the tasks");
  41:     //cancel all the tasks
  42:     tokenSource2.Cancel();
  43:  
  44:     Console.ReadLine();
  45: }
原文地址:https://www.cnblogs.com/wildboar/p/2071929.html