任务工厂

 1         private static void TaskFactoryDemo()
 2         {
 3             Task taskParent = new Task(() =>
 4             {
 5                 //向应该被取消的 System.Threading.CancellationToken 发送信号。
 6                 CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
 7 
 8                 //提供对创建和计划 Task<TResult> 对象的支持。
 9                 //   cancellationToken:
10                 //     将指派给由此 System.Threading.Tasks.TaskFactory 创建的任务的默认取消标记(除非在调用工厂方法时显式指定另一个取消标记)。
11                 //
12                 //   creationOptions:
13                 //     在使用此 System.Threading.Tasks.TaskFactory<TResult> 创建任务时要使用的默认选项。
14                 //
15                 //   continuationOptions:
16                 //     在使用此 System.Threading.Tasks.TaskFactory<TResult> 创建任务时要使用的默认选项。
17                 //
18                 //   scheduler:
19                 //     要用于计划使用此 System.Threading.Tasks.TaskFactory<TResult> 创建的任何任务的默认计划程序。 null 值指示应使用 System.Threading.Tasks.TaskScheduler.Current。
20                 TaskFactory<int> taskFactory = new TaskFactory<int>(cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
21 
22                 //创建并启动3个子任务
23                 //一个Task<int>类型的数组,初始化为3个返回类型为int的任务
24                 Task<int>[] childTasks = new Task<int>[]{
25 
26                     //StartNew 创建并启动 任务。
27                     taskFactory.StartNew(()=>Sum(cancellationTokenSource.Token,10000)),
28                     taskFactory.StartNew(()=>Sum(cancellationTokenSource.Token,20000)),
29                     //int.MaxValue 此处会抛出OverflowException
30                     taskFactory.StartNew(()=>Sum(cancellationTokenSource.Token,int.MaxValue))
31                 };
32 
33                 //循环给每一个子任务添加ContinueWith(延续任务)
34                 for (int i = 0; i < childTasks.Length; i++)
35                 {
36                     //有任何一个子任务失败(OnlyOnFaulted),就取消(Cancel())所有子任务
37                     childTasks[i].ContinueWith(t => cancellationTokenSource.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
38                 }
39 
40                 //创建一个延续任务,它将在提供的一组任务全部完成(ContinueWhenAll)后马上开始。
41                 // 参数:
42                 //   tasks:
43                 //     继续执行的任务所在的数组。
44                 //
45                 //   continuationFunction:
46                 //     在 tasks 数组中的所有任务完成时要异步执行的函数委托。
47                 //
48                 //   cancellationToken:
49                 //     将指派给新的延续任务的取消标记。
50                 taskFactory.ContinueWhenAll(
51                     childTasks,
52                     //所有子任务均完成后,从未出错/未取消的子任务中获取返回的最大值
53                     continuationFunction => continuationFunction.Where(t => !t.IsCanceled && !t.IsFaulted).Max(t => t.Result),
54                     CancellationToken.None)
55                     //将最大值传给另一个任务来显示最大结果
56                     //(延续任务在导致前面的任务转换为其最终状态的相同线程上运行。 如果在创建延续任务时已经完成前面的任务,则延续任务将在创建此延续任务的线程上运行。)
57                     //创建根据 continuationOptions 中指定的条件加以执行的延续任务。
58                     //ExecuteSynchronously指定应同步执行延续任务。
59                     .ContinueWith(t => Console.WriteLine("The maximum is:" + t.Result), TaskContinuationOptions.ExecuteSynchronously);
60             });
61 
62             //子任务完成后也显示任何未处理的异常
63             taskParent.ContinueWith(p =>
64             {
65                 //将所有文本放到一个StringBuilder中,并只调用Console.WriteLine
66                 //这个任务可能和上面的任务并行执行,这样做可以避免输出变得不连续
67                 StringBuilder stringBuilder = new StringBuilder("The following exception(s) occurred:" + Environment.NewLine);
68                 //将 System.AggregateException 实例平展到一个新实例。
69                 foreach (var e in p.Exception.Flatten().InnerExceptions)
70                 {
71                     stringBuilder.AppendLine(" " + e.GetType().ToString());
72                 }
73                 Console.WriteLine(stringBuilder.ToString());
74             }, TaskContinuationOptions.OnlyOnFaulted);
75 
76             //启动父任务,使它能启动子任务
77             taskParent.Start();
78         }
79 
80         /// <summary>
81         /// n以内正整数求和
82         /// </summary>
83         /// <param name="cancellationToken">取消操作的通知</param>
84         /// <param name="n"></param>
85         /// <returns></returns>
86         private static int Sum(CancellationToken cancellationToken, int n)
87         {
88             int sum = 0;
89             for (; n > 0; n--)
90             {
91                 //在取消标识引用的CancellationTokenSource上调用Cancel
92                 //如果已请求取消此标记,则引发 System.OperationCanceledException
93                 cancellationToken.ThrowIfCancellationRequested();
94 
95                 //检查n值,若太大,则抛出OverflowException
96                 checked { sum = sum + n; }
97             }
98             return sum;
99         }

      注意:调用TaskFactory或TaskFactory<TResult>的静态ContinueWhenAll和ContinueWhenAny方法时,无论前置任务是如何完成的,ContinueWhenAll和ContinueWhenAny都会执行延续任务。

 

posted on 2018-05-12 11:21  庭前花满留晚照  阅读(298)  评论(1编辑  收藏  举报

导航