2012-07-15 15 views
5

¿Cómo ejecuto un método asincrónico desde un método de controlador y devuelvo un HttpStatusCodeResult (200), sin que el delegado asincrónico finalice prematuramente su ejecución?¿Cómo ejecuto correctamente un método Async en ASP.net MVC?

Estoy trabajando en una aplicación asp.net y una de mis acciones es muy lenta (10-30 seg). Quiero devolver un HttpStatusCodeResult (200) y seguir ejecutando mi función. El functo no necesita devolver nada, pero aún así no es realmente un caso de incendio y olvidarlo ya que devuelvo una respuesta al servidor de inmediato con HttpStatusCodeResult.

Intenté usar delegados, pero parece que una vez que devuelvo el código de estado de la acción, el delegado deja de ejecutar. Otra opción es crear un servicio de Windows, pero sería como usar una bazuca para matar una mosca. Recibo muy pocas solicitudes, por lo que los recursos y el rendimiento no son un problema en mi caso. Escuché que ThreadPool.QueueUserWorkItem es una opción, pero ¿cuál es la más adecuada para mi caso?

+0

Esta podría ser su mejor opción: [Usar un controlador asincrónico en ASP.NET MVC] (http://msdn.microsoft.com/en-us/library/ee728598.aspx) –

+0

pero creo que solo optimiza el uso del grupo de subprocesos, quiero decir que no puedo devolver el código httpstatus y seguir ejecutando, consulte la _Conversión de métodos de acción síncrona en métodos de acción asincrónica_ sección –

Respuesta

1

Crea una clase estática que gestione esta operación de larga ejecución. Esta clase será responsable de crear subprocesos para realizar la tarea y también proporciona una forma de verificar el estado de cualquier operación en curso (es decir, si todavía está en progreso o ha finalizado, y si es así, cuál es el resultado).

Su método MVC Controller utiliza esta clase para hacer el trabajo y presentar la información de estado o los datos procesados ​​completados al usuario.

Algo como esto:

public ActionResult GetSomething(String id) { 
    TaskResult result = TaskClass.GetStatus(id); 
    if(result == null) { // the task has not been run, so start it up 
     TaskClass.StartNew(id); 
     return new View("PleaseWait"); 
    } else if(!result.IsFinished) { 
     return new View("PleaseWait"); 
    } else { 
     return View("Results", result); 
    } 
} 

public static class TaskClass { 
    private static Dictionary<String,TaskResult> _tasks; 
    public static TaskResult GetStatus(String id) { 
     // TODO: Make this code thread-safe 
     if(_tasks.ContainsKey(id)) return _tasks[id]; 
     return null; 
    } 
    public static void Start(String id) { 
     _tasks.Add(id, new TaskResult("Working")); 
     Thread thread = new Thread(SomeExpensiveOperation); 
     thread.Start(id); 
    } 
} 

Al final de SomeExpensiveOperation no sería código que marca el TaskResult como terminada.

+0

Parece que podría funcionar. La única parte que no puedo entender es: * ¿quién todavía está escuchando el resultado de la sincronización una vez que el método del controlador ha terminado de ejecutarse? * –

+0

Nadie. No es necesario ser un oyente. Simplemente almacene los resultados de la operación completa en la memoria hasta que el cliente lo solicite. Vea mi respuesta actualizada para un ejemplo. En este caso, uso un diccionario (tenga en cuenta que mi código no es seguro para subprocesos y está plagado de errores, pero debería poder obtener la idea general). – Dai

Cuestiones relacionadas