2012-07-05 25 views
7

sólo estoy usando las nuevas funciones del controlador asíncrono en MVC 4 como se describe aquí http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4MVC controlador asíncrono ASP.NET 4 Devolución de llamada

Si tengo una acción que puede tomar 10-20 segundos para ejecutar Me gustaría ofrecer algún tipo de barra de estado para notificar al usuario del progreso. ¿Las características de Async tienen algo para ayudarlo?

EDIT: Voy a tomar una puñalada en cómo voy a tratar de hacerlo y ver si hay maneras mejores

public async Task<ActionResult> GizmosAsync() 
{ 
    return View("Gizmos", await GetGizmosAsync()); 
} 

private void GetGizmosAsync() 
{ 
    for(int i=0; i<10; i++) 
    { 
     lock(_locker) 
     { 
      _statusMessage = String.Format("{0} of 10", i); 
     } 
     DoSomethingLongRunning(); 
    } 
} 

public ActionResult Status() 
{ 
    return Json(new { Status = _statusMessage }); 
} 

static readonly object _locker = new object(); 

static string _statusMessage = ""; 

.... 

<script> 

setTimeout(displayStatus, 1000); 

function displayStatus() { 
    $.post("/controller/status", function(data) { 
    alert(data.Status); 
    }); 
} 

</script> 

Respuesta

15

controladores asincrónicos es sólo un mecanismo para liberar hilos de la ThreadPool en IIS con el fin para poder manejar las solicitudes entrantes durante la carga pesada, pero la comunicación con el cliente sigue siendo la solicitud-respuesta habitual.

Las barras de estado y el tipo generalmente son solo javascript que muestran algo en la pantalla hasta que finaliza la solicitud de ajax. No creo que MVC4 sea de ayuda en esa parte.

Puede hacer algo como esto: https://stackoverflow.com/a/68503/1373170 para mostrar un "procesamiento ..." <div> durante llamadas ajax.

EDITAR: Si necesita el progreso del cliente real y la interacción (como progreso real), que debe salir SignalR http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx Y este post relacionados: Async Controllers (MVC), long running process with "stops"

+0

Sí, ya hacer algo así, pero si es el mismo mensaje durante 10 segundos la gente piensa que el sistema ha colgado. – Craig

+0

Bueno, sé que puede no sonar apropiado, pero a veces la "ilusión" de progreso es justo lo que necesitan los usuarios. Por ejemplo, si sabe que su tarea lleva un promedio de 15 segundos, automatice una barra de progreso a través de esa duración usando js. Sé que puede parecer una tontería para el usuario, pero en realidad hay algunos casos en los que almacenar un progreso parcial en alguna parte, como una base de datos, y tener una encuesta del lado del cliente para el progreso exacto es exagerado. –

+0

No había pensado en SignalR, probablemente funcionaría bien. – Craig

5

Este artículo parece describir lo que desear:

ASP.NET MVC 3: Async jQuery progress indicator for long running tasks

controlador:

public class HomeController : Controller 
{ 
    private static IDictionary<Guid, int> tasks = new Dictionary<Guid, int>(); 

    public ActionResult Index() 
    { 
     return View(); 
    } 

    public ActionResult Start() 
    { 
     var taskId = Guid.NewGuid(); 
     tasks.Add(taskId, 0); 

     Task.Factory.StartNew(() => 
     { 
      for (var i = 0; i <= 100; i++) 
      { 
       tasks[taskId] = i; // update task progress 
       Thread.Sleep(50); // simulate long running operation 
      } 
      tasks.Remove(taskId); 
     }); 

     return Json(taskId); 
    } 

    public ActionResult Progress(Guid id) 
    { 
     return Json(tasks.Keys.Contains(id) ? tasks[id] : 100); 
    } 
} 

Vista:

<script type="text/javascript"> 

function updateMonitor(taskId, status) { 
    $("#" + taskId).html("Task [" + taskId + "]: " + status); 
} 

$(function() { 
    $("#start").click(function (e) { 
    e.preventDefault(); 
    $.post("Home/Start", {}, function (taskId) { 

    // Init monitors 
    $("#monitors").append($("<p id='" + taskId + "'/>")); 
    updateMonitor(taskId, "Started"); 

    // Periodically update monitors 
    var intervalId = setInterval(function() { 
     $.post("Home/Progress", { id: taskId }, function (progress) { 
     if (progress >= 100) { 
      updateMonitor(taskId, "Completed"); 
     clearInterval(intervalId); 
     } else { 
      updateMonitor(taskId, progress + "%"); 
     } 
     }); 
     }, 100); 
    }); 
    }); 
}); 
</script> 
<div id="monitors"></div> 
+1

No es bueno si está utilizando un entorno de AppDomain múltiple con equilibrio de carga. – divinci

Cuestiones relacionadas