提问人:N D 提问时间:3/22/2023 最后编辑:Theodor ZouliasN D 更新时间:3/23/2023 访问量:44
使用 Task.WaitAll 检索并发异步 API 调用的结果时出现问题
Problem with retrieving the results of concurrent asynchronous API calls using Task.WaitAll
问:
我正在开发一个检查外部服务(API等)健康状况的应用程序。 为了显示我需要的运行状况,我需要对每个服务进行 API 调用。
我在使用异步函数检索 API 调用的结果时遇到问题。
我有两种方法可以检索 API 端点的信息。但我不明白为什么它不起作用。
public async Task<List<HealthStatus>> ExecuteApiCallsAsync()
{
var apis = new[] {
new { Name = "API 1", Url = "https://localhost:7157/api/healthstatus" },
new { Name = "API 2", Url = "https://localhost:7150/api/healthstatus" }
};
var tasks = new List<Task<HealthStatus>>();
try
{
// for(int i = 0; i < apis.Length; i++)
// {
// //tasks[i] = GetApiHealthStatusAsync(apis[i].Name, apis[i].Url);
// //tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
// }
foreach (var api in apis)
{
tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
}
Task.WaitAll(tasks.ToArray());
return tasks.ToList();
}
catch (Exception ex)
{
}
}
public async Task<HealthStatus> GetApiHealthStatusAsync(string apiName, string apiUrl)
{
var healthStatus = new HealthStatus { Name = apiName };
try
{
using var client = new HttpClient();
var result = await client.GetAsync(apiUrl);
if (result != null && result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
healthStatus = JsonConvert.DeserializeObject<HealthStatus>(content);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
healthStatus.Condition = "Unhealthy";
}
return healthStatus;
}
答:
0赞
Md. Rayhan Khan
3/23/2023
#1
问题似乎出在以下代码行上:
返回任务。ToList(); tasks 是一个 Task 对象列表,对它调用 ToList() 将简单地创建一个具有相同 Task 对象的新列表。若要实际检索任务的结果,需要对每个 Task 对象调用 Result 属性。
一种方法是使用 await Task.WhenAll(tasks) 方法而不是 Task.WaitAll(tasks.ToArray())。这将等待所有任务完成,并将其结果作为 HealthStatus 对象数组返回。
下面是修改后的 ExecuteApiCallsAsync 方法:
public async Task<List<HealthStatus>> ExecuteApiCallsAsync()
{
var apis = new[] {
new { Name = "API 1", Url = "https://localhost:7157/api/healthstatus" },
new { Name = "API 2", Url = "https://localhost:7150/api/healthstatus" }
};
var tasks = new List<Task<HealthStatus>>();
try
{
foreach (var api in apis)
{
tasks.Add(GetApiHealthStatusAsync(api.Name, api.Url));
}
var results = await Task.WhenAll(tasks);
return results.ToList();
}
catch (Exception ex)
{
// Handle exception
return null;
}
}
请注意,您还应该正确处理异常,方法是重新引发异常或返回 null。
评论
catch