我有下面的代码,看起来像ApiClass中的await语句会导致函数“AControllerMethodInAspMVC”在每个api.GetResultFromAnotherService完成之前返回。
主线程在所有子线程完成之前返回。有没有办法解决这个问题?
private ApiClass api = new ApiClass();
[HttpPost]
public Task<JsonResult> AControllerMethodInAspMVC()
{
var arrayOfItem = …;
List<object> resultObjs = new List<object>();
var resultLock = new SemaphoreSlim(1);
Parallel.ForEach(
arrayOfItem,
async item =>
{
var result = await api.GetResultFromAnotherService(item.id);
var resultObj = new {
// prepare resultObj from result
};
await resultLock.WaitAsync();
resultObjs.add(resultObj);
resultLock.Release();
});
return Task.FromResult(this.Json(resultObjs));
}
Public class ApiClass
{
Public async Task<string> GetResultFromAnotherService(string id)
{
….
…
await Call AnAsyncOperationToGetResult
…
…
}
}
答案 0 :(得分:0)
Parallel.ForEach()
无法理解async
,因此您的lambda编译为async void
。这意味着,只要您点击await
,ForEach()
就会认为迭代已完成并继续进行另一次迭代。
解决这个问题的一种方法是首先同时启动所有服务调用,然后等待所有服务调用使用Task.WhenAll()
完成:
public async Task<JsonResult> AControllerMethodInAspMVC()
{
var arrayOfItem = …;
var tasks = arrayOfItem.Select(
item => api.GetResultFromAnotherService(item.id));
return await Task.WhenAll(tasks);
}
如果您想限制并行执行服务调用的次数,可以使用SemaphoreSlim
的{{1}}:
WaitAsync()