キャンセルするとキャンセル発生元のタスクは(何もしなければ)最後まで処理が行われ、それ以降の継続タスクは処理されない。
また、OperationCanceledExceptionがスロー・AggregateExceptionに集約される。キャンセル可能性があるタスクは呼び出しもとで補足・後処理すべし。
検証用コード
コンソールアプリケーションで動かしました。
public static class ContinueWithExample3
{
public static void Run()
{
var csource = new CancellationTokenSource();
var task = Task.Factory.StartNew(() =>
{
Console.Write("入力:");
var input = Console.ReadLine();
if (input.ToLower() == "cancel")
{
csource.Cancel();
}
if (input.ToLower() == "error")
{
throw new Exception("何らかのエラー");
}
if (input.ToLower() == "error2")
{
throw new Exception("何らかのエラー2");
}
})
.ContinueWith((t) =>
{
if (t.IsFaulted && t.Exception.Flatten().InnerExceptions.Any((e) => e.Message == "何らかのエラー2"))
{
Console.WriteLine("Task1でタスクの取り消しを行います。");
csource.Cancel();
}
Console.WriteLine("Task1 Cancel:{0}", t.IsCanceled);
Console.WriteLine("Task1 Faulted:{0}", t.IsFaulted);
}, csource.Token)
.ContinueWith((t) =>
{
Console.WriteLine("Task2 Cancel:{0}", t.IsCanceled);
Console.WriteLine("Task2 Faulted:{0}", t.IsFaulted);
}, csource.Token)
.ContinueWith((t) =>
{
Console.WriteLine("Task3 Cancel:{0}", t.IsCanceled);
Console.WriteLine("Task3 Faulted:{0}", t.IsFaulted);
}, csource.Token);
try
{
task.Wait();
}
catch (AggregateException exc)
{
foreach (var innnerExc in exc.InnerExceptions)
{
Console.WriteLine("エラー:{0} {1}",innnerExc.Message,innnerExc.GetType().FullName);
}
}
}
}