在等待Task.WhenAll()中隔离异常

时间:2018-07-19 07:48:54

标签: c# asp.net async-await

执行Task.WhenAll()时隔离异常的正确方法是什么?这样,当其中一个进程(用户)抛出异常时,其他进程将继续处理。

try
{
    var usersToProcess = new List<User>();

    var processes = new List<Task>();
    foreach (var user in usersToProcess)
    {
        var process = // Set up here
        processes.Add(_processHandler.Process(process));
    }

    await Task.WhenAll(processes); // await all here
}
catch (Exception ex)
{
    throw ex;
}

2 个答案:

答案 0 :(得分:2)

所有任务将并行运行,因此即使一个任务引发异常,它也不会停止其他任务以停止执行。参见docs

  

您将Task.WhenAll方法应用于任务集合。的   WhenAll的应用程序将返回直到完成的单个任务   集合中的每个任务都已完成。任务似乎在其中运行   并行,但不创建其他线程。任务可以   以任何顺序完成。

答案 1 :(得分:1)

await Task.WhenAll(processes)将等待processes中的所有任务完成,然后引发由任何任务引发的第一个异常。因此,当您到达catch处理程序时,所有任务都会完成或抛出。

您可以使用计数器变量自己确认:

int count = 0;
try
{
    var usersToProcess = new List<User>();

    const int n = 10;
    var processes = new List<Task>();
    for (int i = 0; i<n; ++i)
    {
        int j = i;
        processes.Add(Task.Run(() =>
        {
            Thread.Sleep(1000);
            Interlocked.Increment(ref count);

            //throw an exception in task 2 and 5
            if (j == 1 || j == 4)
                throw new Exception("...");
        }));
    }

    await Task.WhenAll(processes); // await all here
}
catch (Exception ex)
{
    Console.WriteLine(count); //will always print 10
}

Console.WriteLine(count); //will always print 10

processes中的任务总数将始终按照上述示例代码打印到控制台,无论是否抛出任何任务。