2012-07-05 50 views
7

tôi chỉ sử dụng các tính năng mới Async điều khiển trong MVC 4 như mô tả ở đây http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4ASP.NET MVC 4 async khiển Callback

Nếu tôi có một hành động mà có thể mất 10-20 giây để chạy tôi muốn cung cấp một số loại thanh trạng thái để thông báo cho người dùng về tiến trình. Các tính năng của Async có gì để giúp điều này không?

EDIT: Tôi sẽ mất một đâm vào làm thế nào tôi sẽ cố gắng và làm điều đó và xem liệu có cách nào tốt hơn

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> 

Trả lời

15

Async điều khiển chỉ là một cơ chế để giải phóng chủ đề từ ThreadPool trong IIS để để có thể xử lý các yêu cầu gửi đến trong tải nặng, nhưng việc giao tiếp với khách hàng vẫn là yêu cầu-phản ứng bình thường.

thanh Status và loại thường chỉ javascript hiển thị một cái gì đó trên màn hình cho đến khi kết thúc yêu cầu ajax. Tôi không nghĩ MVC4 sẽ được hỗ trợ trong phần đó.

Bạn có thể làm như sau: https://stackoverflow.com/a/68503/1373170 để hiển thị "đang xử lý ..." <div> trong khi gọi ajax.

EDIT: Nếu bạn cần sự tiến bộ của khách hàng thực tế và tương tác (chẳng hạn như tiến bộ thực sự), bạn nên kiểm tra SignalR http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx Và bài này liên quan: Async Controllers (MVC), long running process with "stops"

+0

Vâng, tôi đã làm điều gì đó như thế nhưng nếu nó là cùng một thông điệp cho 10 giây mọi người nghĩ hệ thống treo. – Craig

+0

Vâng, tôi biết nó có thể không phù hợp, nhưng đôi khi "ảo giác" của tiến bộ chỉ là những gì người dùng cần. Ví dụ: nếu bạn biết công việc của mình mất trung bình 15 giây, hãy tự động hóa thanh tiến trình thông qua thời lượng đó bằng cách sử dụng js. Tôi biết nó có vẻ như lừa của nó cho người sử dụng, nhưng có thực sự là một số trường hợp thực sự lưu trữ tiến từng phần nơi nào đó, giống như một cơ sở dữ liệu và có bạn bỏ phiếu client-side cho sự tiến bộ chính xác chỉ là quá mức cần thiết. –

+0

Tôi đã không nghĩ đến SignalR, nó có lẽ sẽ làm việc tốt. – Craig

5

Bài viết này dường như để mô tả những gì bạn muốn:

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

Bộ điều khiển:

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

Xem:

<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

Không tốt nếu bạn đang sử dụng một tải cân bằng môi trường nhiều AppDomain. – divinci

Các vấn đề liên quan