如何以顺序方式执行异步函数的动态列表?
How to execute a dynamic list of async functions in a sequential way?
我重构了一个 Web API 以依赖于 ASP.NET 核心 3.1 中的 async/await,并且我有以下场景:统计方法按顺序计算指标列表,这些指标是在列表中定义。
readonly Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>> simpleItemActionMap =
new Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>>();
private void InitSimpleStatisticFunctionsMap()
{
simpleItemActionMap.Add(StatisticItemEnum.AllQuestionCount, GetAllQuestionCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AllAnswerCount, GetAllAnswerCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AverageAnswer, GetAverageAnswer);
// other mappings here
}
private async Task<SimpleStatisticItemApiModel> GetAllQuestionCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAllAnswerCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAverageAnswer()
{
// await for database operation
}
代码按顺序遍历每个项目并计算它,重构后它看起来像这样:
itemIds.ForEach(itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = simpleItemActionMap[itemEnumValue]().Result;
payload.SimpleStatisticItemModels.Add(result);
}
});
我知道 Task.Result
might lead to deadlocks,但我找不到任何其他方法来完成这项工作。
问题:如何按顺序执行异步函数的动态列表?
我认为你可以这样做:
itemIds.ForEach(async itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
});
您应该将 ForEach
调用更改为常规 foreach
,然后您可以使用 await
:
foreach (var itemId in itemIds)
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
}
不要使 ForEach
lambda async
;这将导致 async void
方法,您应该 avoid async void
.
我重构了一个 Web API 以依赖于 ASP.NET 核心 3.1 中的 async/await,并且我有以下场景:统计方法按顺序计算指标列表,这些指标是在列表中定义。
readonly Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>> simpleItemActionMap =
new Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>>();
private void InitSimpleStatisticFunctionsMap()
{
simpleItemActionMap.Add(StatisticItemEnum.AllQuestionCount, GetAllQuestionCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AllAnswerCount, GetAllAnswerCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AverageAnswer, GetAverageAnswer);
// other mappings here
}
private async Task<SimpleStatisticItemApiModel> GetAllQuestionCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAllAnswerCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAverageAnswer()
{
// await for database operation
}
代码按顺序遍历每个项目并计算它,重构后它看起来像这样:
itemIds.ForEach(itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = simpleItemActionMap[itemEnumValue]().Result;
payload.SimpleStatisticItemModels.Add(result);
}
});
我知道 Task.Result
might lead to deadlocks,但我找不到任何其他方法来完成这项工作。
问题:如何按顺序执行异步函数的动态列表?
我认为你可以这样做:
itemIds.ForEach(async itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
});
您应该将 ForEach
调用更改为常规 foreach
,然后您可以使用 await
:
foreach (var itemId in itemIds)
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
}
不要使 ForEach
lambda async
;这将导致 async void
方法,您应该 avoid async void
.