执行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;
}
答案 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
中的任务总数将始终按照上述示例代码打印到控制台,无论是否抛出任何任务。