C#发布ID块和合并响应使用异步和等待
问题描述:
我正在写一个方法,接受ID列表来调用API。 该API有一个限制,一次只能接受1000个ID。所以我需要将列表拆分为块并分别进行调用。C#发布ID块和合并响应使用异步和等待
public async Task<List<JObject>> readData(List<int> IDs){
const int APIMaxLimit = 1000;
List<List<int>> chunks = new List<List<int>>();
while (IDs.Any())
{
chunks.Add(IDs.Take(APIMaxLimit).ToList());
IDs= IDs.Skip(APIMaxLimit).ToList();
}
var apiCallTasks = new List<Task>();
foreach (var chunk in chunks)
{
//some logic
apiCallTasks.Add(ReadDatacentersFromResponse(response));
}
await Task.WhenAll(apiCallTasks);
//What do I return?
}
private static async Task<List<JObject>> ReadDatacentersFromResponse(HttpResponseMessage response);
我写了上面的代码,但我不知道如何返回组合值。另外,有没有办法编写更优雅的代码而不使用for循环?
答
从一般观点来看,您可以使用.SelectMany
将多个IEnumerable
组合回单个IEnumerable
。
var data = new List<List<int>>
{
new List<int>{1,2,3},
new List<int>{4,5,6},
new List<int>{7,8,9}
};
var result = data.SelectMany(x => x);
返回:{1, 2, 3, 4, 5, 6, 7, 8, 9}
在你的具体的例子,你可能需要改变
var apiCallTasks = new List<Task>();
到
var apiCallTasks = new List<Task<List<JObject>>>();
允许您访问Result
每一个人Task
的财产,并与合并后返回的结果:
apiCallTasks.SelectMany(r2 => r2.Result);
答
这里是另一种答案,但我更喜欢布拉德利的。尽管我使用ints而不是JObjects,但它是一个简单的完整示例。如果性能是一个问题,你可以看看ArraySegment
。我们的解决方案都不是特别快。
private async Task<List<int>> ReturnInts()
{
return new List<int> { 5 };
}
public async Task<List<int>> PenanceFunction()
{
List<Task<List<int>>> tasks = new List<Task<List<int>>>();
tasks.Add(ReturnInts());
tasks.Add(ReturnInts());
List<int> myResults = new List<int>();
await Task.WhenAll(tasks);
foreach(var t in tasks)
{
myResults.AddRange(t.Result);
}
return myResults;
}
@zzxyz我真的没有看到任何超级复杂的问题。当它使用'async' /'await'时,他需要的答案与它没有直接关系。它可以简化为将一系列数字分成批次,然后重新组合,而不会发生太大的变化。 –
@zzxyz,似乎有点下意识,对我毫无帮助。 OP不需要做任何“'Run()'调用”来使他/她的代码工作。他/她对如何将他/她正在等待的任务的结果与“Task.WhenAll”调用相结合有一个合理的问题。 –
他不?他的任务会自动运行?我错过了什么?我猜测问题是他不知道如何检查任务的返回值。如果这不是问题,请使用'.AddRange()'。完成。我并不想成为一个混蛋,只是说像这样的问题不是学习异步模式的好地方。 Web服务器可能关闭,或者其他一百个问题之一可能会使问题复杂化。 – zzxyz