示例
using System;
using System.Text;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTest2
{
class Program
{
static void Main(string[] args)
{
Task parent = new Task(() =>
{
var cts = new CancellationTokenSource();
// 利用任务工厂可以创建一组共享相同配置的任务
var tf = new TaskFactory<Int32>(
cts.Token,
//用此工厂创建的所有任务都将被视为子任务
TaskCreationOptions.AttachedToParent,
//延续任务在前置任务所在的线程运行,
//如果前置任务已经执行完成,则在创建它的线程中运行
TaskContinuationOptions.ExecuteSynchronously,
//采用默认调度器
TaskScheduler.Default);
// 这个任务创建并启动3个子任务
var childTasks = new[]{
tf.StartNew(()=>Sum(cts.Token, 10000)),
tf.StartNew(()=>Sum(cts.Token, 20000)),
//tf.StartNew(()=>Sum(cts.Token, Int32.MaxValue))//太大,抛出OverflowException
};
// 任何子任务抛出异常,就取消其余子任务
for (Int32 task = 0; task < childTasks.Length; task++)
childTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);
// 所有子任务完成后,从未出错/未取消的任务获取返回的最大值
// 然后将最大值传递给另一个任务来显示最大结果
tf.ContinueWhenAll(
childTasks,
//必须引入System.Linq命名空间,否则会报Where未定义。
completedTasks => completedTasks.Where(
t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
//覆盖TaskFactory的CancellationToken
//这里传None是为了子任务被取消后,此任务依然可以执行
CancellationToken.None)
.ContinueWith(t => Console.WriteLine("The maximum is: "+t.Result),
TaskContinuationOptions.ExecuteSynchronously);
});
// 子任务完成后,也显示任何未处理的异常
parent.ContinueWith(p =>
{
StringBuilder sb = new StringBuilder(
"The following exception(s) occurred:" + Environment.NewLine);
foreach (var e in p.Exception.Flatten().InnerExceptions)
sb.AppendLine(" " + e.GetType().ToString());
Console.WriteLine(sb.ToString());
},
TaskContinuationOptions.OnlyOnFaulted);
// 启动父任务
parent.Start();
Console.ReadLine();
}
private static Int32 Sum(CancellationToken ct, Int32 n)
{
Int32 sum = 0;
for (; n > 0; n--)
{
//在取消标志引用的CancellationTokenSource上调用Cancel,
//下面这行代码就会抛出OperationCanceledException
ct.ThrowIfCancellationRequested();
//如果n太大,会抛出System.OverflowException
checked { sum += n; }
}
return sum;
}
}
}
运行测试