Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
552 views
in Technique[技术] by (71.8m points)

ajax - Implementing a Progress bar for long running task implemented with an ASP.NET MVC 2 AsyncController

After reading the documentation on AsyncControllers in ASP.NET MVC 2, I am wondering what's the best way to implement an ajax progress bar in this scenario. It seems a bit odd that the tutorial does not cover this at all.

I guess implementing an AJAX progress bar involves requires additional action method that returns the status of the current task. However, I am not sure about the best way to exchange information on the status of the task between worker threads and that action method.

My best idea so far was to put information on the curent progress into the Session dictionary along with a unique id, and share that id with the client so that it can poll the status. But perhaps there is a much easier way that I did not notice.

What's the best way to do this?

Thanks,

Adrian

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Very interesting question! Actually it seems that it is not a task for AsyncController. Async controllers are designed for long-running single-HTTP-query operations at server-side. When you are using async action, this could only help you to release ASP.Net worker thread during some long-running operation(s) and allow it to serve other requests while operation is performed. But from client-side point of view it doesn't matter, is this async controller or not. For client this is just single HTTP request.

You need to redesign this using some long-running queries service in your application. Here is example of controller, that could serve such workflow:

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;
    }
}

And here are client-side code, that could interact with this controller:

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
}

This is very basic concept, there are some missed items here, but I hope you will get the main idea. Also it's up to you how to design components of this system, for example:

  • use singleton for OperationsService, or not;
  • where and how long operation result should be stored (DB? Cache? Session?);
  • is it really required to manually release resources and what to do when client stopped to monitor operation (user closed browser) etc.

Best luck!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...