加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 异步调用永远不会在Asp.Net MVC中返回

发布时间:2020-12-15 23:47:02 所属栏目:百科 来源:网络整理
导读:我返回一个基本上调用两个异步操作的列表: [HttpPost]public ActionResult List(DataSourceRequest command,ProductListModel model){ var categories = _productService.GetAllProducts(model.SearchProductName,command.Page - 1,command.PageSize); var
我返回一个基本上调用两个异步操作的列表:

[HttpPost]
public ActionResult List(DataSourceRequest command,ProductListModel model)
{
    var categories = _productService.GetAllProducts(model.SearchProductName,command.Page - 1,command.PageSize);

    var gridModel = new DataSourceResult
    {
        Data = categories.Select(async x =>
        {
            var productModel = x.ToModel();
            var manufacturer = await _manufacturerService.GetManufacturerById(x.ManufacturerId);
            var category = await _categoryService.GetCategoryById(x.CategoryId);

            productModel.Category = category.Name;
            productModel.Manufacturer = manufacturer.Name;
            return productModel;
        }),Total = categories.TotalCount
    };
    return Json(gridModel);
}

这是一个ajax请求(来自客户端),但在前端它永远不会返回.有没有僵局?

解决方法

从几条评论和@ usr的答案中建立我的答案:

>上面代码中的数据实际上是IEnumerable< Task< ProductModel>>,而不是IEnumerable< ProductModel>.这是因为传递给Select的lambda是异步的.
>最有可能的是,JSON序列化程序正在遍历此结构并枚举Task< ProductModel>上的属性.实例,包括Result.

在这种情况下,我在我的博客why accessing Result will cause a deadlock上解释.简而言之,这是因为异步lambda将在等待之后尝试在ASP.NET请求上下文中继续执行.但是,ASP.NET请求上下文在对Result的调用时被阻止,将该线程锁定在该请求上下文中,直到Task< T>完成.由于异步lambda无法恢复,因此无法完成该任务.所以这两件事情都在相互等待,你会遇到经典的僵局.

有一些建议使用await Task.WhenAll,我通常会同意.但是,在这种情况下,您正在使用Entity Framework并出现此错误:

A second operation started on this context before a previous asynchronous operation completed.

这是因为EF不能在同一个db上下文中同时执行多个异步调用.有几种方法可以解决这个问题;一种是使用多个db上下文(实质上是多个连接)来同时进行调用. IMO更简单的方法是顺序进行异步调用而不是并发:

[HttpPost]
public async Task<ActionResult> List(DataSourceRequest command,ProductListModel model)
{
  var categories = _productService.GetAllProducts(model.SearchProductName,command.PageSize);

  var data = new List<ProductModel>();
  foreach (var x in categories)
  {
    var productModel = x.ToModel();
    var manufacturer = await _manufacturerService.GetManufacturerById(x.ManufacturerId);
    var category = await _categoryService.GetCategoryById(x.CategoryId);

    productModel.Category = category.Name;
    productModel.Manufacturer = manufacturer.Name;
    data.Add(productModel);
  }

  var gridModel = new DataSourceResult
  {
    Data = data,Total = categories.TotalCount
  };
  return Json(gridModel);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读