首页 > 解决方案 > 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()块。有人可以向我解释为什么这种行为吗?

标签: c#for-loopasynchronousforeachasync-await

解决方案


我变了

return await Task.Run(() =>

return await Task.Run(async () =>

并且 foreach 块的行为符合预期。


推荐阅读