在MVC控制器的动作中执行async/await

BAD*_*EED 13 c# asp.net asp.net-mvc async-await

Index在ASP.net MVC控制器中有一个动作.此操作调用(除其他外)一个私有操作,该操作对具有大量行的SQL表进行计数.返回的号码将插入视图包属性中.

public ActionResult Index() 
{
    // do things
    ViewBag.NumberOfRows = NumberOfRows();
    return View();
}

private string NumberOfRows()
{
    // sql connection and row count
    return numberOfRows;
}
Run Code Online (Sandbox Code Playgroud)

这有效,但在执行所有操作之前,我看不到索引页面,甚至是行数.相反,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();
}
Run Code Online (Sandbox Code Playgroud)

这有效.但这真的是异步吗?我想念一下,还有其他方法吗?

Pra*_*ana 15

它的async调用,但这里要理解的一件重要事情就是async在这种情况下你的控制器动作:线程(asp.net线程池)处理请求返回线程池(asp.net请求线程池).

这意味着它释放thead池的线程来处理更多请求(这意味着异步控制器操作只是帮助处理更多请求它并不意味着它减少了处理时间,它只是让你的服务器响应更快).一旦在async/await下运行完成,来自请求线程池的新线程就会进行进一步处理.

如果你想要真正的异步页面,即想让你的页面更具响应性,我建议使用.ajax()jQuery函数或使用Asp.net MVC中提供的ajax extesion 进行调用.


Yuv*_*kov 7

这有效.但这真的是异步吗?

事实上,一旦您查询数据库(这是一个IO绑定操作),就可以释放ASP.NET线程池线程而不是使用它来阻塞,直到查询完成.

异步并不意味着"将此请求返回给调用者,我将在稍后完成执行",这有点像您期望的那样.它不会破坏HTTP请求 - 响应协议.async不能实现你想要的东西.

如果您希望立即完成请求,则需要在某个后台线程上对其进行排队,并在操作完成后将数据推送到客户端.