2012-07-05 170 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