【发布时间】:2019-02-28 20:33:11
【问题描述】:
我有一个检索部署列表的方法。对于每个部署,我想检索一个关联的版本。因为所有调用都是对外部 API 进行的,所以我现在有一个 foreach 循环,可以在其中进行这些调用。
public static async Task<List<Deployment>> GetDeployments()
{
try
{
var depjson = await GetJson($"{BASEURL}release/deployments?deploymentStatus=succeeded&definitionId=2&definitionEnvironmentId=5&minStartedTime={MinDateTime}");
var deployments = (JsonConvert.DeserializeObject<DeploymentWrapper>(depjson))?.Value?.OrderByDescending(x => x.DeployedOn)?.ToList();
foreach (var deployment in deployments)
{
var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
deployment.Release = JsonConvert.DeserializeObject<Release>(reljson);
}
return deployments;
}
catch (Exception)
{
throw;
}
}
这一切都很好。但是,我根本不喜欢 foreach 循环中的 await。我也认为这不是好的做法。我只是不知道如何重构它,所以调用是并行的,因为每个调用的结果都用于设置部署的属性。
如果有任何关于如何使此方法更快的建议,我将不胜感激,并尽可能避免在 foreach 循环中使用 await-ing。
【问题讨论】:
-
你可以使用
Parallel.Foreach()或使用 PLinq 或创建一个任务 foreachGetJson()并等待他们都看到:Use Task.WaitAll() to handle awaited tasks? -
或者创建一个
List<Task<...>>,将每个调用添加到api然后await Task.WhenAll(tasks)gigi.nullneuron.net/gigilabs/avoid-await-in-foreach -
这是TPL DataFlow的工作,是的
-
@J.vanLangen 谢谢,虽然我已经读到
Parallel.ForEach是推荐的 CPU 密集型任务,而不是与 IO 相关的任务。正如@Ric 提到的,我确实可以将每个对API 的调用放在List<Task<..>>中,然后稍后按ID 映射正确的Release。我还将研究提到的 TPL DataFlow @Saruman。谢谢!
标签: c# foreach async-await