キャンセルサポートを追加するために、次のコードを改善したいと思います。基本的に、私がする必要があるのは、子が例外をスローしたら、すべての子と親タスクをキャンセルすることです。私は学習体験として以下のコードを書きました。AggregateException
すべての子供たちが終わって初めて見ることができますが、私はそれを望んでいません。
static int GetSum()
{
var parent = Task<int>.Factory.StartNew(() =>
{
var children = new Task<int>[100];
for (var i = 0; i < children.Length; i++)
{
var index = i;
children[index] = Task<int>.Factory.StartNew(() =>
{
var randomNumber = new Random().Next(5);
if (randomNumber == 0)
{
throw new Exception();
}
return randomNumber;
}, TaskCreationOptions.AttachedToParent);
}
Task.WaitAll();
Console.WriteLine("Children finished");
return children.Sum(t => t.Result);
});
parent.Wait();
Console.WriteLine("Parent finished");
return parent.Result;
}
方法はわかりませんが、次のものを使用する必要があると思います。
var source = new CancellationTokenSource();
var token = source.Token;
Task.WaitAny
WaitAllの代わりに使用して、AgregateExceptionが次のようにスローされたら、トークンに対してキャンセル要求を行うことができます。
static int GetSum()
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var parent = Task<int>.Factory.StartNew(() =>
{
var children = new Task<int>[100];
for (var i = 0; i < children.Length; i++)
{
var index = i;
children[index] = Task<int>.Factory.StartNew(() =>
{
for (int j = 0; j < 100000; j++)
{
if (!token.IsCancellationRequested)
{
var randomNumber = new Random().Next(5);
if (randomNumber == 0)
{
throw new Exception();
}
return randomNumber;
}
else
{
token.ThrowIfCancellationRequested();
}
}
return 0;
}
, token);
}
try
{
Task.WaitAny(children);
}
catch (AggregateException ae)
{
tokenSource.Cancel();
ae.Handle((task) =>
{
Console.WriteLine("Cancel all others child tasks requested ");
return true;
});
}
Console.WriteLine("Children finished");
return children.Sum(t => t.Result);
});
try
{
parent.Wait();
}
catch (AggregateException aex)
{
aex.Handle((task) =>
{
Console.WriteLine("Cancel child work done ");
return true;
});
}
Console.WriteLine("Parent finished");
return parent.Result;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加