如果我们同步等待结果,使用任务有什么好处吗?
本文关键字:什么 任务 同步 我们 等待 结果 如果 | 更新日期: 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
的决定推迟到调用者的原因,或者提供调用的异步和非异步版本(例如:GetTopMenu
和GetTopMenuAsync
)。如果你强制使用异步调用,那么你就会遇到这样的情况。
您的替代方案是加载视图并通过AJAX异步地进行调用。在这种情况下,您还可以为用户提供视觉反馈。在此场景中使用await
将释放工作进程,以便IIS继续处理请求。