我有一个页面。在该页面中,一些数据基于服务呼叫显示。
此服务电话可能需要一分钟以上。
所以我的索引操作方法就是不要调用这个长时间的服务调用。
但是,通过页面加载时的Ajax调用来调用此服务调用。
这个模型正在运作
我想对此进行修改。
我想在索引操作本身使用Task.Factory.StartNew
在不同的线程中调用此服务调用。即使返回视图,也让该线程在后台工作。我应该能够获得服务线程的结果。单独的Ajax调用。
这里的挑战是如何在Ajax操作方法中访问Index action方法中启动的步骤的结果?
答案 0 :(得分:2)
您可以使用索引操作(启动任务的操作)生成将与此任务关联的唯一编号(可能是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>
当然这只是一个过于简单的例子。在现实世界中,您将拥有视图模型,使用复杂模型进行缓存,而不仅仅是一个简单的字符串,如果此任务需要在完成后产生一些结果,您可以保存有关任务和任务结果的信息执行,......