Controladores assíncronos no asp.net MVC: vantagens reais / como alcançados?


12

Eu tenho trabalhado em um artigo sobre métodos de controlador assíncrono no ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx ) e acho que Eu posso estar perdendo o objetivo.

Considere este método que escrevi, que é muito semelhante a um exemplo do artigo:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

Pelo que entendi, é assim que as coisas se desenrolam no tempo de execução:

  1. Um thread do ASP.NET será criado para uma solicitação HTTP recebida.

  2. Esse segmento (presumivelmente fez alguns trabalhos preliminares necessários) entra no meu método Index () acima.

  3. A execução alcançará a palavra-chave "aguardar" e iniciará um processo de aquisição de dados em outro encadeamento.

  4. O thread "ASP.NET" original retornará ao código que chamou meu método manipulador, com uma instância da classe Task como valor de retorno.

  5. O código de infra-estrutura que chamou meu método manipulador continuará operando no thread "ASP.NET" original, até atingir um ponto em que precisa usar o objeto ActionResult real (por exemplo, para renderizar a página).

  6. O chamador acessará esse objeto usando o membro Task.Result, o que fará com que ele (por exemplo, o encadeamento "ASP.NET") aguarde o encadeamento criado implicitamente na etapa 3 acima.

Não estou vendo o que isso faz em comparação com a mesma coisa sem esperar / assíncrono, exceto por duas coisas que considero insignificantes:

  • O segmento de chamada e o segmento de trabalho criados por aguardar podem operar em paralelo por algum período de tempo (a parte "até" do nº 5 acima). Meu palpite é que o período de tempo é bem pequeno. Quando a infraestrutura chama um método de controlador, acho que geralmente precisa do ActionResult real da chamada do controlador antes que possa fazer muito (se houver) mais.

  • Há alguma nova infraestrutura útil relacionada ao tempo limite e cancelamento de operações de controlador assíncrono de longa duração.

O objetivo de adicionar métodos de controlador assíncrono é supostamente liberar os threads de trabalho do ASP.NET para realmente responder às solicitações HTTP. Esses encadeamentos são um recurso finito. Infelizmente, não estou vendo como o padrão sugerido no artigo realmente serve para conservar esses threads. E, mesmo que isso ocorra, e de alguma forma descarrega o ônus de lidar com a solicitação em algum segmento que não seja do ASP.NET, o que isso faz? Os threads são capazes de lidar com uma solicitação HTTP muito diferente dos threads em geral?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Não necessariamente. asyncnão requer outro segmento ... É uma continuação. Isso pode ser realizado reordenando as instruções no mesmo encadeamento.
Robert Harvey


"A execução alcançará a palavra-chave wait e iniciará um processo de aquisição de dados em outro segmento". você entendeu isso de trás para frente: a espera é quando volta. Tente dividi-lo para salvar o resultado de GetAllAsync () em uma variável e aguardar por isso e ver se fica mais claro.
Esben Skov Pedersen

Respostas:


9

O ASP.Net que não usa a Task Parallel Library (TPL) é limitado no número de solicitações que ele pode manipular simultaneamente pelo número de threads em um pool de threads. O ASP.Net que usa o TPL é limitado pela CPU / memória / E / S das solicitações de processamento da máquina.

A Task Parallel Library (TPL) não consome threads da maneira que você parece pensar. Tarefas não são encadeamentos, são um invólucro em torno de alguma unidade de computação. O agendador de tarefas é responsável por executar cada tarefa em qualquer encadeamento que não esteja ocupado. Em tempo de execução, aguardar uma tarefa não bloqueia o encadeamento, apenas estaciona o estado de execução para que possa prosseguir posteriormente.

Normalmente, uma única solicitação HTTP seria tratada por um único encadeamento, removendo completamente esse encadeamento do pool até que uma resposta seja retornada. Com o TPL, você não está vinculado por essa restrição. Qualquer solicitação recebida inicia uma continuação com cada unidade de cálculo necessária para calcular uma resposta capaz de executar em qualquer encadeamento no conjunto. Com esse modelo, você pode lidar com muito mais solicitações simultâneas do que com o ASP.Net padrão.


Então, quando o thread do ASP.NET é retornado ao pool? Quando a palavra-chave "aguardar" é pressionada?
user1172763

async / waitit + TPL permite que o compilador divida seu código em unidades computacionais independentes, executadas pelo agendador de tarefas. Conceitualmente, um encadeamento é retornado ao pool quando o agendador de tarefas não possui mais tarefas que podem ser executadas e o encadeamento termina o trabalho fornecido a ele.
mortalapeman

Isso é conceitualmente correto e provavelmente uma resposta útil ... no entanto, a realidade é um pouco mais complicada devido à agilidade do encadeamento .
John Wu
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.