Async/wait в действии контроллера MVC

У меня есть действие 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;
}

Это работает, но я не вижу страницу Index, пока все не будет выполнено, даже подсчет строк. Я бы вместо этого выполнил 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();
}

Это работает. Но действительно ли это асинхронно? Мне что-то не хватает, есть ли другой способ сделать это?

Ответ 1

Его вызов async, но одна важная вещь для понимания здесь - это когда вы делаете свое действие с контроллером async в этом случае: thread (из пула потоков asp.net), который обрабатывает запрос, возвращается в пул потоков (запрос asp.net пул потоков).

Это означает, что он освобождает поток этого пула для обработки большего количества запросов (это означает, что действие асинхронного контроллера просто помогает обрабатывать больше запросов, это не значит, что оно сокращает время обработки, оно просто делает ваш сервер более отзывчивым). после операции в async/await завершается новый поток из запроса. Пул потоков продолжает обработку.

Если вам нужна реальная страница асинхронизации, то я хочу сделать вашу страницу более отзывчивой, я предлагаю совершить вызов с помощью функции .ajax() jQuery или используя расширение ajax, доступное в Asp.net MVC.

Ответ 2

Это работает. Но действительно ли это асинхронно?

Асинхронно в том, что после того, как вы запросите свою базу данных (которая является связанной с IO операцией), вы освобождаете поток потока нитей ASP.NET вместо того, чтобы использовать его для блокировки до завершения запроса.

Async не означает "Вернуть этот запрос вызывающему абоненту, и я закончу выполнение позже", что несколько вы ожидаете. Он не нарушает протокол HTTP-запроса-ответа. То, что вы хотите, не достигается с помощью async.

Если вы хотите, чтобы запрос был завершен немедленно, вам нужно поставить его в очередь на некоторый фоновый поток и выталкивать данные на клиентскую сторону после завершения операции.