• Task的知识点总结


    Task是在.NET Framework 4中添加进来的,这是新的namespace:System.Threading.Tasks;它强调的是adding parallelism and concurrency to applications

    现在都是多核的CPU,在系统内,Task Parallel Library能更有效地利用CPU核心。TPL 会动态地按比例调节并发程度,以便最有效地使用所有可用的处理器。TPL 还处理工作分区、ThreadPool 上的线程调度、取消支持、状态管理以及其他低级别的细节操作。对比ThreadPool上的Thread并没有很好地支持Cancel的操作。在语法上,和lambda表达式更好地结合。

    显式创建Task

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class TaskExample1
    {
       public static void Main()
       {
          Thread.CurrentThread.Name = "Main";
    
            // 使用lambda方式,之间提供一个用户delegate,创建一个Task
    
            Task taskA = new Task( () => Console.WriteLine("From taskA."));
    
            // Start
            taskA.Start();
    
            // Output a message from the calling thread.
            Console.WriteLine("From thread '{0}'.", 
                              Thread.CurrentThread.Name);
            //等待task结束
            taskA.Wait();
       }
    }
    
    //       From thread 'Main'.
    //       From taskA.

    任务对象Task提供可在任务的整个生存期内从调用线程访问的方法和属性。例如,可以随时访问任务的 Status 属性,以确定它是已开始运行、已完成运行、已取消还是引发了异常。状态由 TaskStatus 枚举表示。

    简化创建并开始的Task操作版本–直接使用一个操作: System.Threading.Tasks.Task.Run()

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class TaskExample2
    {
       public static void Main()
       {
          Thread.CurrentThread.Name = "Main";
    
          // Define and run the task.
          Task taskA = Task.Run( () => Console.WriteLine("From taskA."));
    
          // Output a message from the calling thread.
          Console.WriteLine("From thread '{0}'.", 
                              Thread.CurrentThread.Name);
          taskA.Wait();
       }
    }
    //       From thread 'Main'.
    //       From taskA.

    TaskFactory创建Task

    TPL提供了工厂类TaskFactory,也可用直接创建Task。 一个操作System.Threading.Tasks.TaskFactory.StartNew, 即可完成创建并开始一个Task.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class TaskExample3
    {
       public static void Main()
       {
          Thread.CurrentThread.Name = "Main";
    
          // 创建task并启动
          Task taskA = Task.Factory.StartNew(() => Console.WriteLine("From taskA."));
    
          // 
          Console.WriteLine("From thread '{0}'.", 
                            Thread.CurrentThread.Name);
          // wait task
          taskA.Wait();                  
       }
    }
    
    //       Hello from thread 'Main'.
    //       Hello from taskA.

    传入参数

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    public class Example
    {
       public static void Main()
       {
          Task[] taskArray = new Task[10];
    
          for (int i = 0; i < taskArray.Length; i++) {
             taskArray[i] = Task.Factory.StartNew( (int param) => {
                                                     Console.WriteLine("Task #{0}.", param);
                                                   },
                                                  i );
          }
          Task.WaitAll(taskArray);     
       }
    }

    Task返回值

    如果一个Task执行方法是有返回值的,可用得到其值。在创建一个task时,其返回的值为Task,表示一个返回类型为T的Task;在taks完成执行后,可用通过Task的Result属性获取结果。

    using System;
    using System.Linq;
    using System.Threading.Tasks;
    
    class Program
    {
        static void Main()
        {
            // lambda表达式创建一个task并执行,并返回值。
            Task<int> task1 = Task<int>.Factory.StartNew(() => 1);
            int i = task1.Result;
    
            // 返回对象
            Task<Test> task2 = Task<Test>.Factory.StartNew(() =>
            {
                string s = ".NET";
                double d = 4.0;
                return new Test { Name = s, Number = d };
            });
            Test test = task2.Result;
    
            // Return an array produced by a PLINQ query
            Task<string[]> task3 = Task<string[]>.Factory.StartNew(() =>
            {
                string path = @"C:UsersPublicPicturesSample Pictures";
                string[] files = System.IO.Directory.GetFiles(path);
    
                var result = (from file in files.AsParallel()
                              let info = new System.IO.FileInfo(file)
                              where info.Extension == ".jpg"
                              select file).ToArray();
    
                return result;
            });
    
            foreach (var name in task3.Result)
                Console.WriteLine(name);
    
        }
        class Test
        {
            public string Name { get; set; }
            public double Number { get; set; }
    
        }
    }

    Continue操作

    如果一个Task开始执行时间依赖于其它的Task的完成,可以使用Continue系列方法。

    using System;
    using System.Threading.Tasks;
    
    public class Example
    {
       public static void Main()
       {                         
          var getData = Task.Factory.StartNew(() => { 
                                                 Random rnd = new Random(); 
                                                 int[] values = new int[100];
                                                 for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                    values[ctr] = rnd.Next();
    
                                                 return values;
                                              } );  
          var processData = getData.ContinueWith((x) => {
                                                    int n = x.Result.Length;
                                                    long sum = 0;
                                                    double mean;
    
                                                    for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                                       sum += x.Result[ctr];
    
                                                    mean = sum / (double) n;
                                                    return Tuple.Create(n, sum, mean);
                                                 } ); 
          var displayData = processData.ContinueWith((x) => {
                                                        return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                             x.Result.Item1, x.Result.Item2, 
                                                                             x.Result.Item3);
                                                     } );                         
          Console.WriteLine(displayData.Result);
       }
    }
    
    // 输出:
    //    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    public class Example
    {
       public static void Main()
       {
          Task[] taskArray = new Task[10];
    
          for (int i = 0; i < taskArray.Length; i++) {
             taskArray[i] = Task.Factory.StartNew( (int param) => {
                                                     Console.WriteLine("Task #{0}.", param);
                                                   },
                                                  i );
          }
          Task.WaitAll(taskArray);     
       }
    }
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    public class Example
    {
       public static void Main()
       {
          Task[] taskArray = new Task[10];
    
          for (int i = 0; i < taskArray.Length; i++) {
             taskArray[i] = Task.Factory.StartNew( (int param) => {
                                                     Console.WriteLine("Task #{0}.", param);
                                                   },
                                                  i );
          }
          Task.WaitAll(taskArray);     
       }
    }
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    public class Example
    {
       public static void Main()
       {
          Task[] taskArray = new Task[10];
    
          for (int i = 0; i < taskArray.Length; i++) {
             taskArray[i] = Task.Factory.StartNew( (int param) => {
                                                     Console.WriteLine("Task #{0}.", param);
                                                   },
                                                  i );
          }
          Task.WaitAll(taskArray);     
       }
    }
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    public class Example
    {
       public static void Main()
       {
          Task[] taskArray = new Task[10];
    
          for (int i = 0; i < taskArray.Length; i++) {
             taskArray[i] = Task.Factory.StartNew( (int param) => {
                                                     Console.WriteLine("Task #{0}.", param);
                                                   },
                                                  i );
          }
          Task.WaitAll(taskArray);     
       }
    }

    而且,可以使用更简化的写法.

    using System;
    using System.Threading.Tasks;
    
    public class Example
    {
       public static void Main()
       {                         
          var displayData = Task.Factory.StartNew(() => { 
                                                     Random rnd = new Random(); 
                                                     int[] values = new int[100];
                                                     for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                        values[ctr] = rnd.Next();
    
                                                     return values;
                                                  } ).  
                            ContinueWith((x) => {
                                            int n = x.Result.Length;
                                            long sum = 0;
                                            double mean;
    
                                            for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                               sum += x.Result[ctr];
    
                                            mean = sum / (double) n;
                                            return Tuple.Create(n, sum, mean);
                                         } ). 
                            ContinueWith((x) => {
                                            return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                 x.Result.Item1, x.Result.Item2, 
                                                                 x.Result.Item3);
                                         } );                         
          Console.WriteLine(displayData.Result);
       }
    }

    Cancel操作

    在TPL中,为Task能cancel执行,提供了CancellationTokenSource和CancellationToken;
    需要完成的工作是:在Task的action执行方法内,周期性地检查CancellationToken的IsCancellationRequested属性。
    示例:

    private var tokenSource = new CancellationTokenSource();
    
        public void Start()
        {
            var token = tokenSource.Token;
            for (int i = 0; i<5; i++>) 
            {
                Task t = Task.Factory.StartNew( () => DoSomeWork(i, token), token);
                Console.WriteLine("Task {0} executing", t.Id);
            }
        }
    
        public void Stop()
        {
            var token = tokenSource.Token;
            tokenSource.Cancel();
        }
    
        void DoSomeWork(int taskNum, CancellationToken ct)
        {
          // 先检查,调度进入时,是否cancel了。
          if (ct.IsCancellationRequested == true) {
             Console.WriteLine("Task {0} was cancelled before it got started.",
                               taskNum);
             ct.ThrowIfCancellationRequested(); // 抛出异常-- 或者 return
          } 
    
          // 正式开始任务。 
          int maxIterations = 100;
    
          // NOTE!!! A "TaskCanceledException was unhandled 
          for (int i = 0; i <= maxIterations; i++) {
             // 
             var sw = new SpinWait();
             for (int j = 0; j <= 100; j++)
                sw.SpinOnce();
    
             if (ct.IsCancellationRequested) {
                Console.WriteLine("Task {0} cancelled", taskNum);
                ct.ThrowIfCancellationRequested(); //抛出异常-- 或者 return
             } 
          } 
        } 
  • 相关阅读:
    跨域上传文件
    算法
    websocket
    Bottle
    爬虫一
    RabbitMQ
    git&github快速入门
    centos6安装SaltStack
    ajax
    Django之Model操作
  • 原文地址:https://www.cnblogs.com/tuboshu/p/10752408.html
Copyright © 2020-2023  润新知