任务工厂
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都会执行延续任务。