异步控制器(MVC),带有“停止”的长时间运行过程
本文关键字:停止 长时间 过程 运行 带有 控制器 异步控制 MVC 异步 | 更新日期: 2023-09-27 18:13:39
我对运行一个长过程很感兴趣,我想在结果开始进来时立即更新UI,而不是等待它完成。
我该怎么做呢?我读过Async控制器,但他们似乎没有为此目的内置任何东西。
只是保存结果在应用程序/会话对象作为结果进来,并使用轮询从客户端?我可以想到几种可能出错的方法(如用户关闭页面,对象永远留在Application对象中-需要自己管理这些对象的过期,额外的服务器负载轮询等)。
任何想法吗?
谢谢
我最近正在尝试解决类似的问题(将长时间运行的服务器操作的实时进度报告给客户端),结果发现SignalR非常适合这种情况。
基本上它是一个包装长轮询和Web Sockets的库,(透明地)使用服务器和客户端上可用的任何东西。
到目前为止我对它只有很好的经验。
可以使用ThreadPool运行长时间运行的任务。它可以更新用户可以轮询的应用程序/会话中的状态。正如你所指出的,这有一些终生的问题。除了你指出的,应用程序池可以回收——但也许这没关系。
该操作的逻辑作用域是什么?它是一个系统类型的长时间运行的任务,有人/许多人需要查询进度吗?还是代表特定用户的长时间运行任务?如果是后者,那么如果用户的会话超时,等等,也没关系。如果是前者,那么你需要更耐用。例如,您可以将任务请求、状态和进度存储在数据库中。这样,在应用程序重新启动时,它可以从它离开的地方恢复,并且任何人都可以轻松查询(如果是系统级任务,则是另一个决策点)。
最后要考虑的是你是否会有多个web角色(web farm/cluster)。如果考虑到这一点,那么使用DB甚至单独的worker角色/服务会更合适。
所以这一切都归结为任务的类型,谁需要监视它,以及持久性要求是什么。如果它只是一个用户任务,保持简单,queueuserworkitem和会话状态。
这篇文章似乎描述了你想要的,简单和无信号:
ASP。. NET MVC 3:用于长时间运行任务的异步jQuery进度指示器
控制器:
公共类HomeController: Controller{private static Dictionary任务= new Dictionary();
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);
});
});
});