• 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: }
  • 相关阅读:
    log4net项目中如何配置,以下详解
    对sql进行分页处理(Oracle版)
    Xcode 默认 字体
    iOS tableView seperator 消失问题
    iOS 解决自定义TabBar使用popToRootViewControllerAnimated重叠问题
    Xcode 代码块
    iOS绘制虚线
    iOS 使用系统相册获取选取图片的名称
    iOS 设置导航栏和状态栏为透明黑色
    iOS textfield设置字符间距
  • 原文地址:https://www.cnblogs.com/wildboar/p/2071929.html
Copyright © 2020-2023  润新知