Реализация индикатора выполнения для длительной задачи, реализованной с помощью ASP.NET MVC 2 AsyncController - PullRequest
15 голосов
/ 01 декабря 2010

После прочтения документации по AsyncControllers в ASP.NET MVC 2 я задаюсь вопросом, каков наилучший способ реализации индикатора выполнения ajax в этом сценарии.Кажется немного странным, что учебник не охватывает это вообще.

Я предполагаю, что реализация индикатора выполнения AJAX требует дополнительного метода действия, который возвращает статус текущей задачи.Однако я не уверен в том, как лучше всего обмениваться информацией о состоянии задачи между рабочими потоками и этим методом действия.

Моя лучшая идея до сих пор заключалась в том, чтобы поместить информацию о текущем прогрессе в словарь сеанса вместе с уникальным идентификатором и поделиться этим идентификатором с клиентом, чтобы он мог опрашивать статус.Но, возможно, есть гораздо более простой способ, который я не заметил.

Какой лучший способ сделать это?

Спасибо,

Адриан

1 Ответ

16 голосов
/ 19 января 2011

Очень интересный вопрос! На самом деле кажется, что это не задача для 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;
    }
}

А вот код на стороне клиента, который может взаимодействовать с этим контроллером:

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
}

Это очень базовая концепция, здесь есть некоторые пропущенные элементы, но я надеюсь, что вы поймете основную идею. Также вам решать, как проектировать компоненты этой системы, например:

  • использовать синглтон для OperationsService, или нет;
  • где и как долго должен храниться результат операции (БД? Кэш? Сессия);
  • действительно ли необходимо вручную высвобождать ресурсы и что делать, когда клиент перестал следить за работой (пользователь закрыл браузер) и т. д.

Удачи!

...