27.5.1 等待任务完成并获取结果
static void Main(string[] args) { Task<int> task = new Task<int>(n => Sum((int)n), 10000); task.Start(); task.Wait(); Console.WriteLine($"sum is {task.Result}"); Console.ReadKey(); } private static int Sum(int n) { int sum = 0; for (; n > 0; n--) { checked { sum += n; } } return sum; }
27.5.2 取消任务
private static int Sum(CancellationToken token, int n) { int sum = 0; for (; n > 0; n--) { token.ThrowIfCancellationRequested(); checked { sum += n; } } return sum; }
static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); Task<int> t = Task.Run(() => Sum(cts.Token, 100000), cts.Token); cts.Cancel(); try { Console.WriteLine("the sum is " + t.Result); } catch (AggregateException ex) { ex.Handle(e => e is OperationCanceledException); Console.WriteLine("sum was canceled"); } Console.ReadKey(); } private static int Sum(CancellationToken token, int n) { int sum = 0; for (; n > 0; n--) { token.ThrowIfCancellationRequested(); checked { sum += n; } } return sum; }
27.5.3 任务完成时自动启动新任务
static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); Task<int> t = Task.Run(() => Sum(cts.Token, 100), cts.Token); Task cwt = t.ContinueWith(task => Console.WriteLine("sum result is " + t.Result)); Console.ReadKey(); } private static int Sum(CancellationToken token, int n) { int sum = 0; for (; n > 0; n--) { token.ThrowIfCancellationRequested(); checked { sum += n; } } return sum; }
static void Main(string[] args) { Task<int> t = Task.Run(() => Sum(100)); t.ContinueWith(task => Console.WriteLine("sum result is " + t.Result), TaskContinuationOptions.OnlyOnRanToCompletion); t.ContinueWith(task => Console.WriteLine("sum throw " + t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted); t.ContinueWith(task => Console.WriteLine("sum was cancel"), TaskContinuationOptions.OnlyOnCanceled); Console.ReadKey(); } private static int Sum(int n) { int sum = 0; for (; n > 0; n--) { checked { sum += n; } } return sum; }
27.5.4 任务可以启动子任务
static void Main(string[] args) { Task<int[]> patientTask = new Task<int[]>(() => { var results = new int[3]; new Task(() => results[0] = Sum(100), TaskCreationOptions.AttachedToParent).Start(); new Task(() => results[1] = Sum(200), TaskCreationOptions.AttachedToParent).Start(); new Task(() => results[2] = Sum(300), TaskCreationOptions.AttachedToParent).Start(); return results; }); var cwt = patientTask.ContinueWith(patient => Array.ForEach(patient.Result, Console.WriteLine)); patientTask.Start(); Console.ReadKey(); } private static int Sum(int n) { int sum = 0; for (; n > 0; n--) { checked { sum += n; } } return sum; }
27.5.6 任务工厂
static void Main(string[] args) { Task patient = new Task(() => { var cts = new CancellationTokenSource(); var tf = new TaskFactory<int>(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); //这个任务创建并启动3个任务 var childTasks = new[] { tf.StartNew(()=>Sum(cts.Token, 100)), tf.StartNew(()=>Sum(cts.Token, 200)), tf.StartNew(()=>Sum(cts.Token, int.MaxValue)) //太大抛异常 }; //任何子任务抛出异常,就取消子任务 for (int task = 0; task < childTasks.Length; task++) { childTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); } //所有子任务完成后,从未出错的/未取消的子任务获取返回最大值 //将最大值传给另一个任务来显示最大值结果 tf.ContinueWhenAll( childTasks, completedTasks => completedTasks.Where(t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) .ContinueWith(t => Console.WriteLine("The maximum is:" + t.Result), TaskContinuationOptions.ExecuteSynchronously); }); //子任务完成后,也显示任何未处理的异常 patient.ContinueWith(p => { StringBuilder sb = new StringBuilder("The following exception(s) occurred:" + Environment.NewLine); foreach (var e in p.Exception.Flatten().InnerExceptions) sb.AppendFormat(" {0}", e.GetType()).AppendLine(); Console.WriteLine(sb.ToString()); }, TaskContinuationOptions.OnlyOnFaulted); //启动父任务,使它能启动子任务 patient.Start(); Console.ReadKey(); } private static int Sum(CancellationToken token, int n) { int sum = 0; for (; n > 0; n--) { checked { sum += n; } } return sum; }
27.5.7 任务调度器
private readonly TaskScheduler m_syncContextTaskScheduler; public MyForm() { InitializeComponent(); m_syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Text = "synchronization Context Task Scheduler Demo"; Visible = true; Width = 400; Height = 100; } private CancellationTokenSource m_cts; protected override void OnMouseClick(MouseEventArgs e) { if (m_cts != null) { m_cts.Cancel(); m_cts = null; } else { Text = "Operation running"; m_cts = new CancellationTokenSource(); Task<int> t = Task.Run(() => Sum(m_cts.Token, 20000), m_cts.Token); t.ContinueWith(task => Text = "result:" + task.Result, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, m_syncContextTaskScheduler); t.ContinueWith(task => Text = "operation cancel :", CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, m_syncContextTaskScheduler); t.ContinueWith(task => Text = "operation faulted :", CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, m_syncContextTaskScheduler); } base.OnMouseClick(e); } private int Sum(CancellationToken token, int n) { int sum = 0; for (; n > 0; n--) { token.ThrowIfCancellationRequested(); checked { sum += n; } } return sum; }