c# - foreach 中的异步调用不执行以下开关
问题描述
我不太了解异步/等待机制,我在 Google 上进行了搜索,但没有找到可接受的答案。
我对以下代码有疑问:
使用.Result
时,switch()
块被执行。
// Here the flow starts - the callee is a VueJS axios ajax call
[Route("ChangeStatusOrders/ValidateStatus")]
[HttpPost]
public async Task<ActionResult> ValidateStatus(OrdersToBeProcessed model)
{
bool success = false;
string message = "";
try
{
model.ReturnData = await _statusBusiness.Validate(model);
success = true;
return Json(new { Success = true, ReturnData = model.ReturnData }, JsonRequestBehavior.AllowGet);
}
catch (ArgumentException ex)
{
message = $"Bad Request {ex.Message}";
_log.Error(message);
Response.StatusCode = 400;
return Json(new { Success = false, ErrorMessage = message }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
message = $"Spomething wrong message here - {ex.Message}";
_log.Error(message);
Response.StatusCode = 500;
return Json(new { Success = false, ErrorMessage = message }, JsonRequestBehavior.AllowGet);
}
finally
{
var param = new
{
model.Orders,
model.NotesText,
model.CompanyID,
model.CompanyName,
model.NewStatus,
model.ReturnData,
model.CodeType,
model.UserID,
model.isInternalUser,
Message = message
};
LogUserAction(ActionType.ChangeStatusOrders, success, param);
}
}
private readonly IDictionary<bool, Func<List<string>, int, List<Order>>> _dic;
constructor()
{
// below methods are not async
_dic = new Dictionary<bool, Func<List<string>, int, List<Pedido>>>
{
{ true, (p) => _orderRepository.GetByID(p) },
{ false, (p) => _orderRepository.GetByCompanyID(p) }
};
}
public async Task<ProcessResults> Validate(OrdersToBeProcessed model)
{
ProcessResults result = new ProcessResults();
bool useOurID = (model.CodeType == 1);
return await Task.Run(() =>
{
try
{
List<string> ordersList = SplitOrders(model.Orders);
List<string> buffer = ordersList.Distinct().ToList();
List<Order> ordersList = new List<Order>(buffer.Count());
buffer.ForEach(item =>
{
var tmp = new Order();
if (useOurID)
tmp.ID = Convert.ToInt64(item);
else
tmp.CompanyId = item;
orderList.Add(tmp);
});
List<Order> foundOrders = _dic[useOurId](buffer);
result.SuccessfullOrders = new List<ProcessedOrder>();
result.NotFoundOrders = new List<ProcessedOrder>();
result.NotAllowedOrders = new List<ProcessedOrder>();
// merge the list of order's id with those one's found in database
List<Orders> union = foundOrders.MergeAndReplace(ordersList).ToList();
foreach (var item in union)
{
ProcessedOrder ret = ValidateAsync(item).Result; // <-- here is an Async call
switch (ret.ProcessedResult)
{
case ProcessedResultEnum.CanBeProcessed:
result.SuccessfullOrders.Add(ret);
break;
case ProcessedResultEnum.OrderNotFound:
result.NotFoundOrders.Add(ret);
break;
case ProcessedResultEnum.CannotBeProcessed:
result.NotAllowedOrders.Add(ret);
break;
}
}
return result;
});
private async Task<Order> ValidateAsync(Order item)
{
ProcessedOrder ret = new ProcessedOrder();
ret.CompanyID = item.CompanyID;
ret.Name = item.Name;
ret.ID = item.ID;
ret.Status = (item.Status?.ID).ToString();
var queueOrderItems = await _queueOrderService.SearchByOrderIdAsync(item.ID);
if (item.ID == 0 || String.IsNullOrEmpty(iitem.CodigoEntidade))
{
ret.Message = "Order not found in database.";
ret.Result = ProcessedResultEnum.OrderNotFound;
}
else if (item.Status == null || queueOrderItems == null)
{
ret.Message = "Order Cannot Be Processed";
ret.Result = ProcessedResultEnum.CannotBeProcessed;
}
else
{
ret.Message = "Order Can Be Processed";
ret.Result = ProcessedResultEnum.CanBeProcessed;
}
return ret;
}
public async Task<SearchBiIdResult> SearchByOrderIdAsync(long orderID )
{
SearchByIDResult ret;
SearchByIDRequest request = new SearchByIDRequest() { OrderID = orderID };
// calls a WCF async method descibed below
SearchByIDResponse response = await _queueOrderItemsClient.SearchByIDAsync(request);
ret = _mapper.Map<SearchByIDResponse>(response);
return ret;
}
// WCF async method definition (in reference.cs)
public System.Threading.Tasks.Task<UI.Services.Business.QueuesService.SearchByIDResponse> SearchByIDAsync(UI.Services.Business.QueuesService.SearchByIDRequest request) {
return base.Channel.SearchByIDAsync(request);
}
但是,如果我替换.Result
为
ProcessedOrder ret = await ValidateAsync(item);
循环立即返回到 foreach 语句,而不执行该switch()
块。有人可以向我解释为什么这种行为吗?
解决方案
我变了
return await Task.Run(() =>
至
return await Task.Run(async () =>
并且 foreach 块的行为符合预期。
推荐阅读
- android - 使用 Retrofit 2 将文件上传到服务器
- css - 如果子项包含类(使用纯 CSS 或打字稿),则将样式应用于 :host
- git - 如何将 Java 项目导入存储库?
- python - Django 查询 object.values() 列表作为参数
- c# - 有没有办法重定向在 .NET Core 项目的构建期间创建的所有文件夹
- python - Python 3 直方图:如何使用 plt.hist() 获取计数和 bin,但不在屏幕上显示直方图?
- python - Python时间序列数据框在while循环中的每个循环设置一个元素
- c# - IoT 事件网格订阅在移动设备中不起作用
- javascript - Node.js:调用递归函数的后处理结果
- docker - TF_FORCE_GPU_ALLOW_GROWTH=true 在多模型服务的张量流中的行为(保存的模型格式)