Вы не можете избежать исключения в ожидании Task.WhenAll (). Это поведение по замыслу. Но вы можете передать статус задания через его значение Result. Просто расширите Result от string до (string Result, bool Success) и верните false Успех из catch без повторного выброса исключения.
public class Controller : ControllerBase
{
private readonly List<string> _names = new List<string>()
{
"name1",
"name2"
};
[HttpGet]
public async Task<ActionResult> Get()
{
// Leaving this processing because it is the same in the original code, maybe there is something here that is relevant
var tasks = _names.ToDictionary(name => name, name => ExecuteRequest(name, async (value) =>
{
return await ReturnOrThrow(value);
}));
await Task.WhenAll(tasks.Values); // Doesn't throw exception anymore, but you can access Success status from Task's Result tuple
var namesThatSucceeded = tasks.Count(t => t.Value.Result.Success);
var namesThatThrewException = tasks.Count(t => !t.Value.Result.Success);
return Ok(new
{
Succeeded = namesThatSucceeded,
Failed = namesThatThrewException
});
}
// The "generic task structure" that runs the request, catches exception if thrown, and re-throws it.
private async Task<(string Result, bool Success)> ExecuteRequest(string name, Func<string, Task<string>> request)
{
try
{
return (await request(name), true);
}
catch (HttpRequestException e)
{
Console.WriteLine(e.Message);
return (null, false);
}
}
// The actual processing
private async Task<string> ReturnOrThrow(string name)
{
if (name == "name1")
{
throw new HttpRequestException();
}
return await Task.FromResult(name);
}
}
Не за что.