2013-12-05 1 views
1

Это первый раз, когда я использую AsyncController (MVC3), и у меня возникли проблемы с пониманием асинхронного действия. Моя задача - импортировать умеренные объемы данных из Excel в базу данных SQL Server, используя Entity Framework. Я думал, что это будет иметь право на асинхронную операцию, и поэтому я написал контроллер для этой цели. Вот код контроллера с асинхронными действиямиАсинхронное действие AsyncController блокирует запросы вместо немедленного возврата

public class CampDonorImportController : AsyncController 
{ 
    public void CampDonorImportAsync(string fileName, int taskId) { 
     ... 
     HttpContext.Application["Progress" + taskId] = 0; 
     AsyncManager.OutstandingOperations.Increment(); 
     Task.Factory.StartNew(task => { 
      //Code to import Excel Data 
     }, taskId); 
    } 

    public ActionResult CampDonorImportCompleted() { 
     return null; 
    } 

    public ActionResult ReportImportProgress(int taskId) { 
     ... 
     return Json(new { Progress = progress, CarryOn = carryOn, Status = status }, JsonRequestBehavior.AllowGet); 

    } 

Я называю действие Async (CampDonorImportAsync) с помощью следующей JQuery кода

$.ajax({ 
     url: importDonorUrl, 
     success: function (data, textStatus, jqXHR) { 
      //Repeatedly call reportImportProgress 
      refreshTimerId = window.setInterval(reportImportProgress, reportTaskProgressTime); 
     }, 
    }); 

reportImportProgress Javascript функции вызывает действие ReportImportProgress(), который отображает текущий прогресс асинхронное действие.

$.ajax({ 
     url: reportTaskProgressUrl, 
     complete: function (jqXHR, textStatus, errorThrown) { 
      var json = $.parseJSON(jqXHR.responseText); 
      if (!json.CarryOn) { 
       endImportInit(); 
       alert(json.Status); 
      } 
     }, 
    }); 

Вопрос заключается в том, что вызов метода асинхронным (CampDonorImportAsync) блокирует другие запросы от одной и той же странице, например ReportImportProgress() выше. Я думал, что вызов действия Async должен немедленно вернуться, так что могут быть сделаны другие запросы, даже если задача Async все еще продолжается. Я не уверен, почему запрос Async заблокирован и ждет завершения задачи, вместо немедленного возвращения. Есть идеи ?

ответ

3

Как я опишу в своем блоге async does not change the HTTP protocol. С помощью HTTP вы получаете один ответ на запрос, и все.

Надежное решение несколько сложнее, чем вы думаете. Вам нужна надежная очередь (например, Azure queue) и независимый сервер (например, роль рабочего Azure), который обрабатывает запросы из этой очереди. Затем ваш контроллер MVC может просто добавить запрос в очередь и вернуться. Затем ваш интерфейс может опросить для завершения или получить уведомление через что-то вроде SignalR.

+0

Да, я как бы неправильно понял все асинхронное действие. Его единственный поток IIS, который возвращается в пул, Request все еще живет. Фактически, я наткнулся на возможное решение, которое работает. Вот ссылка http://blog.janjonas.net/2012-01-02/asp_net-mvc_3-async-jquery-progress-indicator-long-running-tasks. Фактически, метод Action, который запускает новую задачу, возвращает (не дожидаясь фоновой задачи), а затем я могу вызывать действие ReprotImportProgress через регулярные промежутки времени. Он работает, но я не уверен в недостатках (если есть) – Jatin

+1

@Nirvan: Сохранение длительных задач в памяти, таких как ссылка, которую вы опубликовали, весьма опасна. У меня есть [еще одно сообщение в блоге] (http://blog.stephencleary.com/2012/12/returning-early-from-aspnet-requests.html), в котором более подробно рассматривается это. –

+0

Я реализовал решение, упомянутое в вашем сообщении в блоге. Я протестировал его, и функция Tokellation Token позволяет задачу изящно выйти. Как правило, мы будем архивировать нашу базу данных до фоновой обработки, и поэтому ваше решение подходит для моего дела. – Jatin