Tengo una acción de Index en el controlador ASP.net MVC. Esta acción llama (entre otras cosas) a una acción privada que hace un conteo en una tabla SQL con un gran conjunto de filas. El número devuelto se insertará en una propiedad de bolsa de visualización.
public ActionResult Index() { // do things ViewBag.NumberOfRows = NumberOfRows(); return View(); } private string NumberOfRows() { // sql connection and row count return numberOfRows; } Esto funciona, pero no puedo ver la página de índice hasta que todo se ejecuta, incluso el recuento de filas. En cambio, Index la acción para que se complete de inmediato, incluso si la función privada aún no se ha completado. Entonces, cuando se haya completado el conteo, establezca un valor para la propiedad view bag. Ahora mismo he hecho esto:
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(); }Esto funciona. Pero, ¿es esto realmente asíncrono? ¿Me estoy perdiendo algo, hay otra forma de hacer esto?
Es una llamada async , pero una cosa importante que debe entender aquí es cuando hace que la acción de su controlador sea async en ese caso: subproceso (del grupo de subprocesos de asp.net) cuya solicitud de manejo regresa al grupo de subprocesos (grupo de subprocesos de solicitud de asp.net).
Eso significa que libera el hilo del grupo de anuncios para manejar más solicitudes (significa que la acción del controlador asíncrono solo ayuda a manejar más solicitudes, no significa que disminuya su tiempo de procesamiento, solo hace que su servidor sea más receptivo). una vez que se completa la operación bajo async/await, el nuevo subproceso del grupo de subprocesos de solicitud realiza un procesamiento adicional.
Si desea una página asíncrona real, es decir, desea que su página responda mejor, le sugiero que haga una llamada usando la función .ajax() de jQuery o usando la extensión ajax disponible en Asp.net MVC.
Esto funciona. Pero, ¿es esto realmente asíncrono?
Es asíncrono en el hecho de que una vez que consulta su base de datos (que es una operación vinculada a IO), libera el subproceso ASP.NET Thread-Pool en lugar de usarlo para bloquear hasta que finaliza la consulta.
Async no significa "Devolver esta solicitud a la persona que llama y terminaré de ejecutarla más tarde" , que es algo de lo que espera. No rompe el protocolo de solicitud-respuesta HTTP. Lo que quieres no se logra mediante async.
Si desea que la solicitud se complete de inmediato, deberá ponerla en cola en algún subproceso en segundo plano y enviar los datos al lado del cliente una vez que se complete la operación.
En lugar de asíncrono, use Task.Run:
Task.Run(() => MethodToExecuteInBackground(methodParameters)).ConfigureAwait(false).GetAwaiter();También deberá eliminar el modificador asíncrono del método de índice de su controlador.
Ahora su método de controlador regresará inmediatamente mientras MethodToExecuteInBackground se apaga y funciona en segundo plano.
Tenga en cuenta que esto vinculará un subproceso de grupo de subprocesos hasta que finalice MethodToExecuteInBackground .