Очень интересный вопрос! На самом деле кажется, что это не задача для 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,
или нет;
- где и как долго должен храниться результат операции (БД? Кэш?
Сессия);
- действительно ли необходимо вручную высвобождать ресурсы и что делать, когда
клиент перестал следить за работой
(пользователь закрыл браузер) и т. д.
Удачи!