我有一个部分操作,需要调用从数据库调用返回任务的异步方法。由于我无法进行异步部分操作,因此我需要等待任务完成:
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在这种情况下,我们正在同步等待它?
答案 0 :(得分:4)
我从您的问题描述中假设GetTopMenu
返回Task
,因此should actually be called 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点。这种情况,因为我们正在同步等待它?
正确。通过将(异步)数据库访问包装在(同步)部分操作中,代码会使async
的好处无效。
这是平台的限制(ASP.NET MVC)。请投票on the issue和on uservoice。
答案 1 :(得分:3)
您将从将执行该逻辑的线程池中召唤一个线程,但将阻止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);
}
答案 2 :(得分:3)
您不应该在ASP.NET中使用Task.Run
。您仍受限于单个HTTP请求/响应时间范围,它不会加快内容交付速度,只会引入额外的线程切换,请检查this。
所以,你的行动应该是这样的:
public ActionResult TopMenu()
{
var topMenu = return _menuService.GetTopMenu();
//view model population code goes here
return PartialView(viewModel);
}
如果部分视图可能需要一段时间才能渲染,请考虑使用以下技术:
答案 3 :(得分:1)
你是正确的..这通常是你推迟使用Task
决定调用者,或提供调用的异步和非异步版本的原因(例如:{{1}和GetTopMenu
)。如果强制使用异步调用,那么就会遇到这样的情况。
您可以选择加载视图并通过AJAX异步拨打电话。您还可以在此方案中为用户提供可视反馈。在此方案中使用GetTopMenuAsync
将释放IIS的工作进程以继续提供请求。