Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待每个循环的异步调用_C#_Foreach_Async Await - Fatal编程技术网

C# 等待每个循环的异步调用

C# 等待每个循环的异步调用,c#,foreach,async-await,C#,Foreach,Async Await,我有一个检索部署列表的方法。对于每个部署,我希望检索关联的版本。因为所有调用都是对外部API进行的,所以我现在有一个foreach循环,在其中进行这些调用 public static async Task<List<Deployment>> GetDeployments() { try { var depjson = await GetJson($"{BASEURL}release/deployments?deploymentSta

我有一个检索部署列表的方法。对于每个部署,我希望检索关联的版本。因为所有调用都是对外部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;
    }
}
公共静态异步任务GetDeployments() { 尝试 { var depjson=await GetJson($“{BASEURL}发布/部署?部署状态=成功&definitionId=2&definitionEnvironmentId=5&minStartedTime={MinDateTime}”); var部署=(JsonConvert.DeserializeObject(depjson))?.Value?.OrderByDescending(x=>x.DeployedOn)?.ToList(); foreach(部署中的var部署) { var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”); deployment.Release=JsonConvert.DeserializeObject(reljson); } 返回部署; } 捕获(例外) { 投掷; } } 这一切都很好。但是,我根本不喜欢foreach循环中的
wait
。我也认为这不是一个好的做法。我只是不知道如何重构它以使调用并行,因为每个调用的结果都用于设置部署的属性


如果您能就如何加快此方法提出任何建议,并尽可能避免foreach循环中的
wait
-ing,我将不胜感激。

如果我理解正确,并且您希望使
var reljson=wait GetJson
parralel:

试试这个:

Parallel.ForEach(deployments, (deployment) =>
{
    var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
    deployment.Release = JsonConvert.DeserializeObject<Release>(reljson);
});
Parallel.ForEach(部署,(部署)=>
{
var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”);
deployment.Release=JsonConvert.DeserializeObject(reljson);
});
您可以限制并行执行的数量,例如:

Parallel.ForEach(
    deployments,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    (deployment) =>
{
    var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
    deployment.Release = JsonConvert.DeserializeObject<Release>(reljson);
});
Parallel.ForEach(
部署,
新的并行选项{MaxDegreeOfParallelism=4},
(部署)=>
{
var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”);
deployment.Release=JsonConvert.DeserializeObject(reljson);
});
您可能还希望能够打破循环:

Parallel.ForEach(deployments, (deployment, state) =>
{
    var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
    deployment.Release = JsonConvert.DeserializeObject<Release>(reljson);
    if (noFurtherProcessingRequired) state.Break();
});
Parallel.ForEach(部署,(部署,状态)=>
{
var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”);
deployment.Release=JsonConvert.DeserializeObject(reljson);
if(无需进一步处理)state.Break();
});

您现在所做的事情没有错。但是有一种方法可以一次调用所有任务,而不是等待单个任务,然后处理它,然后等待另一个任务

以下是您如何扭转这种局面:

等待一个->处理->等待一个->处理…

进入

wait all->process->done

将其转换为:

foreach (var deployment in deployments)
{
    var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
    deployment.Release = JsonConvert.DeserializeObject<Release>(reljson);
}
foreach(部署中的var部署)
{
var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”);
deployment.Release=JsonConvert.DeserializeObject(reljson);
}
致:

var-deplTasks=deployments.Select(d=>GetJson($“{BASEURL}release/release/{d.ReleaseId}”);
var reljsons=wait Task.WhenAll(deplTasks);
对于(var index=0;index
首先,您要列出未完成任务的列表。然后等待它,并得到一组结果(
reljson
)。然后您必须对它们进行反序列化,并将其分配给
Release

通过使用
wait Task.WhenAll()
您可以同时等待所有任务,因此您应该可以从中看到性能的提升


如果有输入错误,请告诉我,我没有编译此代码。

Fcin建议启动所有任务,等待它们全部完成,然后开始反序列化获取的数据

但是,如果第一个任务已经完成,但是第二个任务没有完成,并且第二个任务在内部等待,那么第一个任务可能已经开始反序列化。这将缩短进程空闲等待的时间

因此,不是:

var deplTasks = deployments.Select(d => GetJson($"{BASEURL}release/releases/{d.ReleaseId}"));
var reljsons = await Task.WhenAll(deplTasks);
for(var index = 0; index < deployments.Count; index++)
{
    deployments[index].Release = JsonConvert.DeserializeObject<Release>(reljsons[index]);
}
var-deplTasks=deployments.Select(d=>GetJson($“{BASEURL}release/release/{d.ReleaseId}”);
var reljsons=wait Task.WhenAll(deplTasks);
对于(var index=0;index
我建议做以下细微的改变:

// async fetch the Release data of Deployment:
private async Task<Release> FetchReleaseDataAsync(Deployment deployment)
{
    var reljson = await GetJson($"{BASEURL}release/releases/{deployment.ReleaseId}");
    return JsonConvert.DeserializeObject<Release>(reljson);
}

// async fill the Release data of Deployment:
private async Task FillReleaseDataAsync(Deployment deployment)
{
    deployment.Release = await FetchReleaseDataAsync(deployment);
}
//异步获取部署的发布数据:
专用异步任务FetchReleaseDataAsync(部署)
{
var reljson=await GetJson($“{BASEURL}release/release/{deployment.ReleaseId}”);
返回JsonConvert.DeserializeObject(reljson);
}
//异步填充部署的发布数据:
专用异步任务FillReleaseDataAsync(部署)
{
deployment.Release=await-FetchReleaseDataAsync(部署);
}
然后,您的程序与Fcin建议的解决方案类似:

IEnumerable<Task> tasksFillDeploymentWithReleaseData = deployments.
    .Select(deployment => FillReleaseDataAsync(deployment)
    .ToList();
await Task.WhenAll(tasksFillDeploymentWithReleaseData);
IEnumerable tasksFillDeploymentWithReleaseData=deployments。
.Select(部署=>FillReleaseDataAsync(部署)
.ToList();
等待Task.WhenAll(tasksFillDeploymentWithReleaseData);
现在,如果第一个任务在获取发布数据时必须等待,则第二个任务开始,第三个任务等。如果第一个任务已完成获取发布数据,但其他任务正在等待其发布数据,则第一个任务已开始反序列化,并将结果分配给deployment.release,然后第一个任务完成了

例如,如果第7个任务获得了数据,但第2个任务仍在等待,则第7个任务可以反序列化数据并将其分配给deployment.Release。任务7已完成

这将一直持续到所有任务完成。使用此方法,等待时间会减少,因为一旦一个任务有了数据,它就计划开始反序列化

,您可以使用、使用或创建一个任务foreach
GetJson()
IEnumerable<Task> tasksFillDeploymentWithReleaseData = deployments.
    .Select(deployment => FillReleaseDataAsync(deployment)
    .ToList();
await Task.WhenAll(tasksFillDeploymentWithReleaseData);