当其中一个子任务抛出异常时取消子任务
本文关键字:子任务 一个 抛出异常 取消 | 更新日期: 2023-09-27 17:54:25
我想改进以下代码以添加取消支持。基本上,我需要做的是一旦子任务抛出异常,就取消所有子任务以及父任务。我写了下面的代码作为学习经验。我只能在所有孩子完成后才能看到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,并在抛出aggreateexception时向令牌发出取消请求像这样
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;
}