2012-07-05 16 views
7

jestem tylko przy użyciu nowych funkcji asynchroniczny kontroler w MVC 4, jak opisano tutaj http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4ASP.NET MVC 4 asynchroniczny kontroler oddzwaniania

Jeśli mam działanie, które może trwać 10-20 sekund, aby uruchomić Chciałbym zapewnić jakiś pasek stanu, aby powiadomić użytkownika o postępie. Czy funkcje Async mają cokolwiek, aby temu zaradzić?

EDIT: wezmę ukłucie w jaki sposób będę próbować zrobić i zobaczyć, czy są jakieś lepsze sposoby

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> 

Odpowiedz

15

kontrolery asynchroniczne jest właśnie mechanizm zwalniania wątki z puli wątków w IIS w celu aby móc obsłużyć przychodzące żądania podczas dużego obciążenia, ale komunikacja z klientem pozostaje jak zwykle reakcją na żądanie.

Paski stanu i sortowanie to zwykle tylko javascript wyświetlający coś na ekranie, dopóki zapytanie ajaxowe nie zostanie zakończone. Nie sądzę, że MVC4 będzie pomocna w tej części.

Możesz zrobić coś takiego: https://stackoverflow.com/a/68503/1373170, aby wyświetlić "przetwarzanie ..." <div> podczas wywołań ajaxowych.

EDIT: Jeśli potrzebujesz prawdziwego postępu klienta i interakcji (np rzeczywistego postępu), należy sprawdzić SignalR http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx a to związane wpis: Async Controllers (MVC), long running process with "stops"

+0

Tak, ja już coś takiego zrobić, ale jeśli jest to ta sama wiadomość przez 10 sekund ludzie uważają system zawiesił. – Craig

+0

Wiem, że to może nie brzmieć właściwie, ale czasami "złudzenie" postępu jest tym, czego potrzebują użytkownicy. Na przykład, jeśli wiesz, że twoje zadanie trwa średnio 15 sekund, zautomatyzuj pasek postępu przez ten czas, używając js. Wiem, że to może wydawać się wygłupiać użytkownika, ale naprawdę są pewne przypadki, w których faktycznie przechowywanie częściowe postępy gdzieś, jak bazy danych i po pollingu stronie klienta dla dokładnego postępu jest po prostu przesada. –

+0

Nie myślałem o SignalR, prawdopodobnie by działało dobrze. – Craig

5

Ten artykuł wydaje się opisać to, co chcą:

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

Kontroler:

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); 
    } 
} 

Widok:

<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

Nie jest dobre, jeśli używasz zrównoważonego środowiska wielu aplikacji AppDomain. – divinci

Powiązane problemy