使用ASP.NET MVC 2 AsyncController实现长时间运行任务的进度条

Adr*_*ore 15 ajax asp.net-mvc asynccontroller asp.net-mvc-2

在阅读ASP.NET MVC 2中的AsyncControllers文档之后,我想知道在这种情况下实现ajax进度条的最佳方法是什么.这个教程根本没有涵盖这一点似乎有点奇怪.

我想实现一个AJAX进度条涉及需要额外的操作方法来返回当前任务的状态.但是,我不确定在工作线程和该操作方法之间交换有关任务状态的信息的最佳方法.

到目前为止,我最好的想法是将有关当前进度的信息与唯一的ID一起放入会话字典中,并与客户端共享该ID,以便它可以轮询状态.但也许有一种我没有注意到的更简单的方法.

最好的方法是什么?

谢谢,

阿德里安

Vic*_*din 16

非常有趣的问题!实际上它似乎不是一项任务AsyncController.异步控制器专为服务器端长时间运行的单HTTP查询操作而设计.当您使用异步操作时,这只能帮助您在某些长时间运行的操作期间释放ASP.Net工作线程,并允许它在执行操作时提供其他请求.但从客户端的角度来看无关紧要,是不是这个异步控制器.对于客户端,这只是单个HTTP请求.

您需要在应用程序中使用一些长时间运行的查询服务来重新设计它.以下是可以为此类工作流程提供服务的控制器示例:

public class LongOperationsController : Controller
{
    public ActionResult StartOperation(OperationData data)
    { 
        Guid operationId = Guid.NewGuid(); // unique identifier for your operation
        OperationsService.DoStartOperation(operationId, data); // service starts to perform operation using separate thread
        return new JsonResult(operationId); // operation id should be sent to client to allow progress monitoring
    }

    public ActionResult GetOperationStatus(Guid operationId) 
    {
        var status = OperationsService.GetStatus(operationId); // this method returns some object, that describes status of operation (e.g. progress, current task etc.)
        return new JsonResult(status); // returning it to client
    }

    public ActionResult GetOperationResult(Guid operationId)
    {
        var result = OperationsService.GetOperationResult(operationId); // this should throw exception if operation is not yet completed
        return new JsonResult(result);
    }

    public ActionResult ClearOperation(Guid operationId)
    {
        OperationsService.ClearOperationResult(operationId); // we should delete operation result if it was handled by client
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里是客户端代码,可以与此控制器交互:

var operationId;
function startOperation(data) {
    $.post('/LongOperations/StartOperation', data, function(response) {
        operationId = response; // store operationId
        startOperationMonitoring(); // start
    }, 'json');
}

function startOperationMonitoring() {
    // todo : periodically call updateOperationStatus() to check status at server-side
}

function updateOperationStatus() {
    // todo : get result of GetOperationStatus action from controller 
    // todo : if status is 'running', update progress bar with value from server, if 'completed' - stop operation monitoring and call finishOperation()
}

function finishOperation() {
    // todo : get result of GetOperationResult action from controller and update UI
    // todo : call ClearOperation action from controller to free resources
}
Run Code Online (Sandbox Code Playgroud)

这是非常基本的概念,这里有一些错过的项目,但我希望你能得到主要的想法.此外,您还可以自行决定如何设计此系统的组件,例如:

  • 使用singleton for OperationsService,不是;
  • 应该存储操作结果的位置和时间(DB?Cache?Session?);
  • 是否真的需要手动释放资源以及当客户端停止监视操作(用户关闭的浏览器)等时该怎么做

好运!