如何在调用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);
}

如何在调用Task.WaitAll之前提示异常

您可以使用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;
}