[英]async/await in MVC controller's action
我在ASP.net MVC控制器中有一个Index
动作。 此操作调用(除其他外)一个私有操作,该操作对具有大量行的SQL表进行计数。 返回的号码将插入视图包属性中。
public ActionResult Index()
{
// do things
ViewBag.NumberOfRows = NumberOfRows();
return View();
}
private string NumberOfRows()
{
// sql connection and row count
return numberOfRows;
}
这有效,但在执行所有操作之前,我看不到索引页面,甚至是行数。 相反,即使私人功能尚未完成,我也会立即完成Index
操作。 比计数完成时,为视图包属性设置一个值。 现在我已经这样做了:
private async Task<string> NumberOfRows()
{
SqlConnection connection = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "SELECT SUM (row_count) FROM sys.dm_db_partition_stats WHERE object_id=OBJECT_ID('aTable') AND (index_id=0 or index_id=1)";
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
await connection.OpenAsync();
reader = await cmd.ExecuteReaderAsync();
string numberOfRows = "N/A";
while (await reader.ReadAsync())
{
numberOfRows = reader.GetInt64(0).ToString();
}
connection.Close();
return numberOfRows ;
}
public async Task<ActionResult> Index(FormCollection form){
// do things;
ViewBag.NumberOfRows = await NumberOfRows();
return View();
}
这有效。 但这真的是异步吗? 我想念一下,还有其他方法吗?
它的async
调用,但这里要理解的一件重要事情就是当你在这种情况下使控制器操作async
时:处理请求的线程(asp.net线程池)返回到线程池(asp.net请求线程池)。
这意味着它释放thead池的线程来处理更多请求(这意味着异步控制器操作只是帮助处理更多请求它并不意味着它减少了处理时间,它只是让你的服务器响应更快)。 一旦在async / await下运行完成,来自请求线程池的新线程就会进行进一步处理。
如果你想要真正的异步页面,即想让你的页面更具响应性,我建议使用jQuery的.ajax()
函数或使用Asp.net MVC中提供的ajax extesion进行调用。
这有效。 但这真的是异步吗?
事实上,一旦您查询数据库(这是一个IO绑定操作),就可以释放ASP.NET线程池线程而不是使用它来阻塞,直到查询完成。
异步并不意味着“将此请求返回给调用者,我将在稍后完成执行” ,这正是您所期待的。 它不会破坏HTTP请求 - 响应协议。 async不能实现你想要的东西。
如果您希望立即完成请求,则需要在某个后台线程上对其进行排队,并在操作完成后将数据推送到客户端。
而不是异步,使用Task.Run:
Task.Run(() => MethodToExecuteInBackground(methodParameters)).ConfigureAwait(false).GetAwaiter();
您还需要从控制器索引方法中删除异步修改器。
现在,当MethodToExecuteInBackground
关闭并且在后台执行某些操作时,您的控制器方法将立即返回。
请注意,这将占用线程池线程,直到MethodToExecuteInBackground
完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.