vista una tutorial paso mvc multiples modelos modelo form ejemplo crear controlador c# asp.net-mvc nhibernate

una - mvc c# windows forms ejemplo



En asp.net-mvc, ¿cómo puedo ejecutar una operación costosa sin ralentizar la experiencia del usuario? (9)

Tengo un sitio web asp.net-mvc y estoy usando nhibernate para mi ORM.

Tengo una acción de controlador actual que realiza una actualización básica de CRUD (consulta un elemento de la base de datos y luego actualiza un grupo de valores y se confirma a la tabla de la base de datos). Luego devuelve una respuesta json simple al cliente para indicar el éxito o el error.

public ActionResult UpdateEntity(MyEntity newEntity) { var existingEntity = GetFromRepository(newEntity.Id); UpdateExistingEntity(newEntity, existingEntity); return Json(SuccessMessage); }

En ciertos casos (asumiendo el éxito de la confirmación y si se cambian ciertos campos en mi objeto) ahora quiero activar algunas acciones adicionales (como enviar un correo electrónico a un grupo de personas y ejecutar algún código que genere un informe) pero no quiero disminuir la velocidad Abajo la experiencia de usuario de la persona que está realizando la actualización. Así que mi preocupación es que si hice esto:

public ActionResult UpdateEntity(MyEntity newEntity) { var existingEntity = GetFromRepository(newEntity.Id); bool keyFieldsHaveChanged = UpdateExistingEntity(newEntity, existingEntity); if (keyFieldsHaveChanged) { GenerateEmails(); GenerateReports(); } return Json(SuccessMessage); }

que sería demasiado lento para la experiencia del usuario de alguien actualizando. ¿Hay alguna forma (asyngc?) Para que una operación costosa se desencadene de una acción del controlador pero no se ralentice la acción del controlador debido a esta?


Creo que realmente quieres un rol de trabajador similar al de Windows Azure.

http://www.microsoft.com/windowsazure/features/compute/

No estoy seguro de cómo implementar mejor eso en MVC puro sin la cola de Azure. Y, según el lugar donde se aloje (host de Internet, su propio servidor con root, etc.), existen complicaciones.


Debe realizar operaciones asíncronas y controladores asíncronos para no bloquear el grupo de subprocesos y no para que otros usuarios del sitio web sufran. Cuando la tarea se está ejecutando durante mucho tiempo, el subproceso tomado del grupo de subprocesos asp.net se reserva y no se devuelve al grupo hasta que se complete la operación. Si habrá muchas tareas de ejecución simultánea, se reservarán muchos subprocesos, por lo que es muy probable que otros usuarios que visiten su sitio sufran con la espera. LAS OPERACIONES DE ASYNC NO HACERÁ NINGÚN CÓDIGO. Le aconsejo que use controladores asíncronos solo para los hilos que escribí sobre los anteriores, pero eso no es suficiente. Creo que debería usar algunos enlaces o ajax para activar la operación en el servidor y permitir que el usuario continúe su navegación en el sitio. Una vez que finaliza la operación, en la actualización de la página siguiente, se debe notificar al usuario que la tarea ha terminado de ejecutarse. Y aquí hay otra prueba de que los códigos comerciales no deben escribirse en el controlador. Deberías haber separado los servicios para eso.


Esta es una pregunta antigua, por lo que creo que necesita actualización.

Recomiendo usar HangFire ( http://hangfire.io ). Con esto, simplemente puede poner en cola su trabajo incluso en la aplicación web . HangFire se asegurará de que el trabajo se ejecute al menos una vez.

// Static methods are for demo purposes BackgroundJob.Enqueue( () => Console.WriteLine("Simple!"));

También puede ver el estado de todos los trabajos en cola en una interfaz de usuario agradable.


Esto no se trata principalmente de asíncrono, ya que leí su pregunta correctamente. Se trata de una operación de larga duración. Debe descargar la operación de ejecución larga en trabajos en segundo plano. Las aplicaciones ASP.NET no son adecuadas para ejecutar trabajos en segundo plano. Puedo ver un par de opciones con las que puedes ir:

  1. Servicio de Windows: esto puede sondear su base de datos para un estado determinado y puede desencadenar una acción desde ese estado en adelante
  2. Servicio WCF: su aplicación ASP.NET puede enviar una solicitud asíncrona al servicio WCF sin esperar la respuesta.
  3. Podría haber otros como BizTalk, pero depende de cómo esté estructurada su aplicación, etc.

Desde la interfaz de usuario, debe poder sondear un temporizador para proporcionar el estado al usuario (si cree que el usuario necesita conocer ese estado de inmediato) o enviar un correo electrónico al usuario cuando se complete la acción.

En una nota al margen, es importante realizar su E / S utilizando operaciones asineadas y otros ya han proporcionado algunos buenos enlaces sobre cómo puede lograrlo.


He hecho esto antes.

La forma más robusta sería utilizar un controlador asíncrono o, mejor aún, un servicio independiente, como un servicio WCF.

Pero en mi experiencia, solo necesitaba hacer una tarea "simple" de una sola línea, como auditorías o informes, como usted dice.

En ese ejemplo, la forma más fácil es disparar una Task :

public ActionResult Do() { SomethingImportantThatNeedsToBeSynchronous(); Task.Factory.StartNew(() => { AuditThatTheUserShouldntCareOrWaitFor(); SomeOtherOperationTheUserDoesntCareAbout(); }); return View(); }

Ese es un ejemplo simple. Puede ejecutar tantas tareas como desee, sincronizarlas, recibir notificaciones cuando terminen, etc.

Actualmente he usado lo anterior para hacer la carga de Amazon S3.


Si está pensando en la experiencia del usuario (el usuario no debe esperar hasta que se realicen estas tareas) y la confiabilidad (las tareas deben ser puestas en cola y ejecutadas incluso si la aplicación se reinicia), puede elegir usar MSMQ.

MSMQ proporciona una solución roubst para las operaciones de sincronización. Es compatible con las operaciones de sincronización, proporciona registros y una API administrada, y tiene como foco principal este tipo de situación.

Echa un vistazo a estos artículos:

Introducción a MSMQ

Programación MSMQ en .Net


Si la intención es devolver JSON inmediatamente y dejar el trabajo intensivo para ejecutarse de forma asíncrona en segundo plano sin afectar la experiencia del usuario, entonces debe iniciar un nuevo subproceso en segundo plano. AsyncController no te ayudará aquí.

Al hacer esto (lo que es cierto), hay muchos argumentos acerca de cómo matar de hambre al grupo de solicitud de subprocesos, pero el argumento contrario es que debe dejar de lado el grupo porque el servidor está ocupado haciendo el trabajo. Por supuesto, lo ideal es que mueva el trabajo a otro servidor por completo a través de colas / sistemas distribuidos, etc., pero esa es una solución compleja. A menos que necesite manejar cientos de solicitudes, no necesita considerar esta opción, ya que es poco probable que alguna vez cause un problema. Realmente depende de los requisitos de escalabilidad de su solución, cuánto tiempo tomará el proceso en segundo plano y con qué frecuencia se llama. La solución más sencilla es la siguiente:

public ActionResult UpdateEntity(MyEntity newEntity) { var existingEntity = GetFromRepository(newEntity.Id); bool keyFieldsHaveChanged = UpdateExistingEntity(newEntity, existingEntity); if (keyFieldsHaveChanged) { ThreadPool.QueueUserWorkItem(o => { GenerateEmails(); GenerateReports(); }); } return Json(SuccessMessage); }