您可以让 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>
当然,这只是一个过于简单的例子。在现实世界的场景中,您将拥有视图模型,对缓存使用复杂的模型,而不仅仅是一个简单的字符串,如果该任务在完成后需要产生一些结果,您可以在其中保存有关任务和任务结果的信息执行,...