情况是,我调用一次 API 来获取租户列表,然后对于每个租户,我必须再次调用以获取租户的使用情况列表。遗憾的是,无法通过一次调用获取所有租户的使用情况。
现在我希望尝试通过使这些调用并发来节省时间。然后在最后一个到达后将它们全部放在一起。到目前为止,我的尝试如下:
public async Task<List<Usage>> GetUsagesAsync2(Task<List<Tenant>> tenants)
{
List<Usage> usages = new List<Usage>();
foreach (var tenant in await tenants)
{
//Generate request
RestRequest request = new RestRequest("tenants/{tenantID}/usages", Method.Get);
request.AddParameter("tenantID", tenant.id, ParameterType.UrlSegment);
request.AddHeader("Authorization", $"Bearer {Token.access_token}");
//Get response
RestResponse response = await _client.ExecuteAsync(request)
.ConfigureAwait(false);
//Validate response
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Failed at Getting usages for a tenant: ");
//Add to list
var t_usage = JsonConvert.DeserializeObject<Wrapper<Usage>>(response.Content);
usages.AddRange(t_usage.items);
}
return usages;
}
代码运行并执行预期的操作,但我不确定它实际上是异步运行的。运行大约需要 7-8 秒,我发现在网页上等待的时间有点长。
最佳答案
这是并行实现:
.NET 6
public async Task<ConcurrentBag<Usage>> GetUsagesAsync2(Task<List<Tenant>> tenants)
{
ConcurrentBag<Usage> usages = new ConcurrentBag<Usage>();
await Parallel.ForEachAsync(await tenants, async (tenant) =>
{
//Generate request
RestRequest request = new RestRequest("tenants/{tenantID}/usages", Method.Get);
request.AddParameter("tenantID", tenant.id, ParameterType.UrlSegment);
request.AddHeader("Authorization", $"Bearer {Token.access_token}");
//Get response
RestResponse response = await _client.ExecuteAsync(request).ConfigureAwait(false);
//Validate response
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Failed at Getting usages for a tenant: ");
//Add to list
var t_usage = JsonConvert.DeserializeObject<Wrapper<Usage>>(response.Content);
usages.AddRange(t_usage.items);
});
return usages;
}
.Net 6 之前的版本
public async Task<ConcurrentBag<Usage>> GetUsagesAsync2(Task<List<Tenant>> tenants)
{
ConcurrentBag<Usage> usages = new ConcurrentBag<Usage>();
var tasks = new List<Task>();
foreach (var tenant in await tenants)
{
tasks.Add(Task.Run(async () =>
{
//Generate request
RestRequest request = new RestRequest("tenants/{tenantID}/usages", Method.Get);
request.AddParameter("tenantID", tenant.id, ParameterType.UrlSegment);
request.AddHeader("Authorization", $"Bearer {Token.access_token}");
//Get response
RestResponse response = await _client.ExecuteAsync(request)
.ConfigureAwait(false);
//Validate response
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Failed at Getting usages for a tenant: ");
//Add to list
var t_usage = JsonConvert.DeserializeObject<Wrapper<Usage>>(response.Content);
usages.AddRange(t_usage.items);
}));
}
await Task.WhenAll(tasks);
return usages;
}
请注意,List
已更改为 ConcurrentBag
,因为它不是线程安全的
关于c# - 调用 API 20 次来生成列表,最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73277096/