如何在调用Task.WaitAll之前提示异常
本文关键字:前提 提示 异常 WaitAll Task 调用 | 更新日期: 2023-09-27 18:21:21
在我的案例中,我通过以下方式创建任务:
IList<Task> Tasks = new List<Task>();
Tasks.Add(Task.Run(async () => { await functionAsync();}));
我需要这些任务无限运行,以便连续处理一些传入的数据。然而,在发生一些致命错误/异常的情况下,我需要通过取消所有任务来结束程序。我举了一个简单的例子来模拟我想要做的事情,但它不起作用。我认为当抛出异常时,任务将被视为结束,WaitAny应该返回AggregatedException,但它似乎并不是实际工作方式。那么,我该如何纠正呢?
public static void Main(string[] args)
{
Console.WriteLine(nameof(Main));
for (int i = 1; i < 5; i++)
{
var i1 = i;
_tasks.Add(Task.Run(async () => { await Tryme(i1); }));
}
try
{
Task.WaitAny(_tasks.ToArray());
}
catch (Exception e)
{
Console.WriteLine("Stop my program if any of the task in _tasks throw exception");
Console.WriteLine(e);
}
Console.ReadLine();
}
private static async Task Tryme(int i)
{
Console.WriteLine($"I'm {i}");
if (i == 3)
{
Console.WriteLine($"{i} is throwing the exception");
throw new Exception("fake one");
}
await Task.Delay(TimeSpan.MaxValue);
}
您可以使用TPL数据流,而不是手动取消整个任务链,如果发生未处理的异常,它会为您伪造整个块,或者如果需要,可以配置为以其他模式运行:
var actionBlock = new ActionBlock<int>(i => TryMe(i));
foreach (var num in Enumerable.Range(0, 100))
{
actionBlock.Post(num);
}
try
{
await actionBlock.Completion();
}
catch (Exception e)
{
// Block finished prematurely, handle exception.
}
注意,Dataflow为您提供了重复功能,无需手动创建任务。
从这篇文章中得到了一些线索。看起来WaitAny不会抛出任何异常。我得到了例外:
int faultIndex = Task.WaitAny(_tasks.ToArray());
if (_tasks[faultIndex].IsFaulted)
{
Console.WriteLine($"{faultIndex} end");
throw _tasks[faultIndex].Exception;
}