如果我们同步等待结果,使用任务有什么好处吗?

本文关键字:什么 任务 同步 我们 等待 结果 如果 | 更新日期: 2023-09-27 17:51:12

我有一个部分操作,需要调用从DB调用返回任务的异步方法。因为我不能有一个异步部分操作,我需要等待任务完成:

public ActionResult TopMenu()
{
  var topMenuTask = Task.Run<IEnumerable<TopMenuItem>>( () => 
    { return _menuService.GetTopMenu(); });
  topMenuTask.Wait();
  //view model population code goes here
  return PartialView(viewModel);
}

这是我的理解做一个异步DB (IO)调用的好处是我们正在重新排队的线程池,所以它可以服务更多的请求,而IO正在完成,但这不是一个moo点在这种情况下,因为我们正在同步等待它?

如果我们同步等待结果,使用任务有什么好处吗?

我从你的问题描述中假设GetTopMenu返回Task,因此实际上应该称为GetTopMenuAsync

在这种情况下,你最好的选择可能是你已经在做的:

public ActionResult TopMenu()
{
  var topMenuTask = Task.Run(() => _menuService.GetTopMenuAsync());
  var topMenu = topMenuTask.Result;
  //view model population code goes here
  return PartialView(viewModel);
}

这是我的理解做一个异步DB (IO)调用的好处是我们正在重新排队的线程池,所以它可以服务更多的请求,而IO正在完成,但这不是一个moo点在这种情况下,因为我们正在同步等待它?

正确的。通过将(异步)DB访问封装在(同步)部分操作中,代码使async的好处无效。

这是平台(ASP. js)的限制。净MVC)。

您将从线程池中调用一个线程来执行该逻辑,但是web请求线程将被阻塞等待结果。所以,不,没有好处。

你为什么不能这样做?:

public async Task<ActionResult> TopMenu()
{
    var topMenu = await Task.Run<IEnumerable<TopMenuItem>>( () => { return _menuService.GetTopMenu(); });
    //view model population code goes here
    return PartialView(viewModel);
}

另一个选择是使用经典的异步MVC方式,但你必须从AsyncController而不是Controller派生你的控制器:

  public void TopMenuAsync()
  {
      AsyncManager.OutstandingOperations.Increment();
      Task.Run<IEnumerable<TopMenuItem>>(() => { return _menuService.GetTopMenu(); })
          .ContinueWith(t =>
          {
              AsyncManager.Parameters["topMenu"] = t.Result;
              AsyncManager.OutstandingOperations.Decrement();
          });
  }
  public ActionResult TopMenuCompleted(TopMenuItem topMenu)
  {
      //view model population code goes here
      return PartialView(viewModel);
  }

你不应该在ASP中使用Task.Run。NET首先。你仍然受到单一HTTP请求/响应时间框架的限制,它不会加速内容传递,只会引入额外的线程切换,检查这个

那么,你的动作应该是这样的:

public ActionResult TopMenu()
{
  var topMenu = return _menuService.GetTopMenu();
  //view model population code goes here
  return PartialView(viewModel);
}

如果你的局部视图可能需要一段时间来渲染,考虑使用这样的技术:

http://blog.michaelckennedy.net/2012/11/13/improve-perceived-performance-of-asp-net-mvc-websites-with-async-partialviews/

你是对的。这通常是您将使用Task的决定推迟到调用者的原因,或者提供调用的异步和非异步版本(例如:GetTopMenuGetTopMenuAsync)。如果你强制使用异步调用,那么你就会遇到这样的情况。

您的替代方案是加载视图并通过AJAX异步地进行调用。在这种情况下,您还可以为用户提供视觉反馈。在此场景中使用await将释放工作进程,以便IIS继续处理请求。