您可以让Index操作(启动任务的那个操作)生成一个与此任务关联的唯一编号(可以是guid)并将条目存储到与此编号关联的缓存中。然后将数字返回到视图。
然后,任务将在后台以无提示的方式运行,并可以更新您存储到缓存中的条目(使用诸如任务进度等信息,或者如果无法实现,则仅表明任务是否已完成) 。任务完成后,从缓存中删除条目。
视图本身可以定期向另一个控制器动作发送AJAX请求并传递任务的ID。该操作将使用该键在缓存中查找相应条目,并返回有关正在运行的任务的视图信息。视图本身可以更新UI。
让我们举个例子吧?
public ActionResult Index()
{
var taskId = Guid.NewGuid().ToString();
var policy = new CacheItemPolicy
{
Priority = CacheItemPriority.NotRemovable,
// Adjust the value to some maximum amount of time that your task might run
AbsoluteExpiration = DateTime.Now.AddHours(1)
};
MemoryCache.Default.Set(taskId, "running", policy);
Task.Factory.StartNew(key =>
{
// simulate a long running task
Thread.Sleep(10000);
// the task has finished executing => we could now remove the entry from the cache.
MemoryCache.Default.Remove((string)key);
}, taskId);
return View((object)taskId);
}
,然后你可以有另一个控制器的行动,将通过AJAX调用视图被要求通知任务的进展:
[HttpPost]
public ActionResult TaskProgress(Guid taskId)
{
var isTaskRunning = MemoryCache.Default.Contains(taskId.ToString());
return Json(new { status = isTaskRunning });
}
,最后你可以有索引视图:
@model string
<div id="status">Task with id @Model has been started and running</div>
<script type="text/javascript">
// start continuous polling at 1s intervals
window.setInterval(function() {
$.ajax({
url: '@Url.Action("TaskProgress", new { taskId = Model })',
type: 'GET',
cache: false,
success: function(result) {
if (!result.status) {
// the task has finished executing => let's notify the user
$('#status').html('The task has finished executing');
}
}
});
}, 1000);
</script>
当然这只是一个简单的例子。在现实世界中,您将拥有视图模型,为缓存使用复杂模型,而不仅仅是一个简单的字符串,在该字符串中可以保存有关任务和任务结果的信息,如果此任务在完成后需要产生某些结果执行,...
你可以设置一个计时器,每隔一段时间触发一次ajax调用。 – derape 2013-03-14 07:12:14
你不能使用AsyncController吗? – 2013-03-14 07:26:16