2012-07-05 199 views
7
我只是用這裏描述 http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4

ASP.NET MVC 4異步控制器回調

如果我有可能需要10-20秒來運行,我想提供一個動作在MVC 4新的異步控制器功能

某種狀態欄來通知用戶進度。異步功能有什麼可以幫助解決這個問題嗎?

編輯:我將在我怎麼會嘗試做一個刺,看看有沒有更好的辦法

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> 

回答

15

異步控制器僅僅是在IIS中,爲了從線程池釋放線程機制能夠在重負載下處理傳入的請求,但與客戶端的通信仍然是通常的請求響應。

狀態欄和排序通常只是在屏幕上顯示一些東西,直到ajax請求結束。我不認爲MVC4在這方面會有所幫助。

你可以這樣做:https://stackoverflow.com/a/68503/1373170在ajax調用期間顯示「正在處理...」<div>

編輯:如果你需要真正的客戶端的進步和交互(如真正的進步),你應該檢查出SignalR http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx 而這個相關的帖子:Async Controllers (MVC), long running process with "stops"

+0

是的,我已經做這樣的事情,但如果它是相同的消息10秒的人認爲該系統已掛起。 – Craig

+0

嗯,我知道這聽起來可能不合適,但有時候,進展的「幻覺」正是用戶需要的。例如,如果您知道您的任務平均需要15秒,則使用js在該持續時間內自動化進度條。 我知道這可能看起來像是愚弄用戶,但實際上有些情況下實際存儲某處的部分進度,比如數據庫,並且您的客戶端輪詢確切進度只是矯枉過正。 –

+0

我沒有想到SignalR,它可能會工作得很好。 – Craig

5

這篇文章似乎描述你想:

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

控制器:

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

查看:

<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

如果您正在使用負載平衡的多個AppDomain環境,則效果不佳。 – divinci