I have a method in which I'm retrieving a list of deployments. For each deployment I want to retrieve an associated release. Because all calls are made to an external API, I now have a foreach-loop in which those calls are made.
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; } } This all works perfectly fine. However, I do not like the await in the foreach-loop at all. I also believe this is not considered good practice. I just don't see how to refactor this so the calls are made parallel, because the result of each call is used to set a property of the deployment.
I would appreciate any suggestions on how to make this method faster and, whenever possible, avoid the await-ing in the foreach-loop.
Parallel.Foreach()or use PLinq or create a task foreachGetJson()and wait them all see: Use Task.WaitAll() to handle awaited tasks?List<Task<...>>, add each call to the api thenawait Task.WhenAll(tasks)gigi.nullneuron.net/gigilabs/avoid-await-in-foreachParallel.ForEachis recommended CPU intensive tasks and not as much for IO related tasks. As @Ric mentioned, I could indeed put each call to the API in aList<Task<..>>and then map the correct Release by id later. I will look into the TPL DataFlow @Saruman mentioned as well. Thanks!