Task、TaskFactory
首次构造一个Task对象时,其的状态是Created。以后当任务启动时,其的状态变成WaitingToRun。Task在一个线程上运行时,其的状态变成Running。任务停止运行,并等待其的任何子任务时,状态变成WaitingForChildrenToComplete。任务完全结束时,它进入以下三个状态之一:RanToCompletion,Canceled或者Faulted。一个Task<TResult>运行完成时,可通过Task<TResult>的Result属性来查询任务的结果,一个Task或者Task<TResult>出错时,可以查询Task的Exception属性来获得任务抛出的未处理的异常,该属性总是返回一个AggregateException对象,他包含所有未处理的异常。
Task提供了几个只读的Boolean属性,IsCanceled,IsFaulted,IsCompleted。注意,当Task处于RanToCompleted,Canceled或者Faulted状态时,IsCompleted返回True。为了判断一个Task是否成功完成,最简单的方法是
if(task.Status == TaskStatus.RanToCompletion)
如果想要得到返回的结果,需使用Task<T>
static void Main(string[] args) { Task<int> task = new Task<int>(o => Sum((int)o), 100); task.Start(); task.Wait(); if(task.Status == TaskStatus.RanToCompletion){ Console.WriteLine(task.Result); } Console.ReadKey(); } static int Sum( int n ) { int sum = 0; for(int i = 0; i <= n ; i++){ //token.ThrowIfCancellationRequested(); sum += i; //Thread.Sleep(2000); } return sum; }
一个任务结束时启动另外一个任务:
static void Main(string[] args) { Task<int> task = new Task<int>(o => Sum((int)o), 100); task.Start(); Task tk = task.ContinueWith(ts => Console.WriteLine(ts.Result)); Console.ReadKey(); } static int Sum( int n ) { int sum = 0; for(int i = 0; i <= n ; i++){ //token.ThrowIfCancellationRequested(); sum += i; //Thread.Sleep(2000); } return sum; }
父任务里面启动子任务
static void Main(string[] args) { Task<int[]> parent = new Task<int[]>(() => { var result = new int[3]; new Task(() => result[0] = Sum(1000), TaskCreationOptions.AttachedToParent).Start(); new Task(() => result[1] = Sum(2000), TaskCreationOptions.AttachedToParent).Start(); new Task(() => result[2] = Sum(3000), TaskCreationOptions.AttachedToParent).Start(); return result; }); var sum = parent.ContinueWith(parentTsk => Array.ForEach(parentTsk.Result, Console.WriteLine)); parent.Start(); Console.ReadKey(); }
TaskFactory[转载]http://blog.csdn.net/chifuqi/article/details/7537423
有时候 需创建一组具有相同状态的Task对象, 可使用System.Threading.Tasks命名空间中TaskFactory<TResult>类型和TaskFactory类型,两者均派生自System.Object。所有任务可共享的属性有:CancellationToken,TaskScheduler, TaskCreationgOption, TaskContinuation.
对此有以下测试目的:
1. 任务工厂内各任务是否异步执行
2. CancellationTokeSource类对协作式的影响
3. 父子任务的影响关系
4. 任务错误信息的捕获
5. ContinueWith 与 ContinueWhenAll的使用
- using System;
- using System.Threading;
- using System.Runtime.Remoting.Messaging;
- using System.Threading.Tasks;
- using System.Linq;
- using System.Text;
- namespace ConsoleApplication1
- {
- class Program
- {
- static void Main(string[] args)
- {
- Task parent = new Task(() =>
- {
- var cts = new CancellationTokenSource();
- var tf = new TaskFactory(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
- var childrenTasks = new[]
- {
- tf.StartNew(() => sum(cts.Token,500)),
- tf.StartNew(() => sum(cts.Token, 100)),
- tf.StartNew(() => sum(cts.Token, 1000)),
- tf.StartNew(() => sum(cts.Token, 200)),
- tf.StartNew(() => sum(cts.Token, 3000)),
- tf.StartNew(() => sum(cts.Token, 400)),
- tf.StartNew(() => sum(cts.Token, 800)),
- };
- for (int task = 0; task < childrenTasks.Length; task++)
- childrenTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
- tf.ContinueWhenAll(childrenTasks,
- completedTasks => completedTasks.Where(
- t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None).ContinueWith(
- t => Console.WriteLine("The max is: " + t.Result),
- TaskContinuationOptions.ExecuteSynchronously);
- });
- parent.ContinueWith(p =>
- {
- StringBuilder sb = new StringBuilder("The following exception(s) occurred: " + Environment.NewLine);
- if (p.Exception != null)
- {
- foreach (var e in p.Exception.Flatten().InnerExceptions)
- sb.AppendLine(" " + e.GetType().ToString());
- }
- Console.WriteLine(sb.ToString());
- }, TaskContinuationOptions.OnlyOnFaulted);
- parent.Start();
- Console.ReadKey();
- }
- private static int sum(CancellationToken token, int n)
- {
- int sum = 0;
- int tmp = n;
- Console.WriteLine();
- Console.WriteLine(n);
- Thread.Sleep(1000);
- for (; n > 0; n--)
- {
- if (token.IsCancellationRequested)
- {
- Console.WriteLine("\nCount is cancelled");
- break;
- }
- checked { sum += n; }
- Console.Write(" n" + n.ToString());
- }
- Console.WriteLine("\n" + tmp.ToString() + "End!");
- return sum;
- }
分析:
1. 代码分为两部分 第二部分用于计算求和,且随时根据token值决定是否结束当前任务;第一部分创建父子线程
2. 父线程parent下利用TaskFactory创建若干同属性线程,均采用默认任务调度方式
3. for循环通知所有线程,如果一个线程faulted其余线程均停止工作。
childrenTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
本身便是个任务,只是这个任务只有满足条件TaskContinuationOptions.OnlyOnFaulted才会执行Action:cts.Cancel()。
4. 当childrenTasks所有任务完成后,取出没故障的(!t.IsFaulted)并不被取消的(!t.IsCanceled)的所有任务的最大值,并打印到屏幕上来。 注意之所以调用CancellationToken.None是因为tf.ContinueWhenAll仍属于parent的子任务,会受到cts.Token影响,所以通过覆盖CancellationToken.None以达到一直显示的目的。
5 parent在所有子任务的sum计算完成后(而不等待tf.ContinueWhenAll(...)执行完成)显示错误信息。
可得到以下结论:
1. 如下图: 任务工厂内各个任务异步执行;parent.ContinueWith与tf.ContinueWhenAll无直接关系。

2. 更改代码为
- var childrenTasks = new[]
- {
- tf.StartNew(() => sum(cts.Token,500)),
- tf.StartNew(() => sum(cts.Token, 100)),
- tf.StartNew(() => sum(cts.Token, Int32.MaxValue)),
- tf.StartNew(() => sum(cts.Token, 200)),
- tf.StartNew(() => sum(cts.Token, 3000)),
- tf.StartNew(() => sum(cts.Token, 400)),
- tf.StartNew(() => sum(cts.Token, 800)),
- };
可得到

从而看出,当某一任务故障后导致cts.Cancel()执行;因此有两个任务(计数为200和3000)被终结.
3.推测:(不知是否正确)
父任务的结束标志是所有子任务完成,但不包括子任务所启动的任务。

浙公网安备 33010602011771号