Методы асинхронного действия и порты завершения ввода-вывода

Одна из причин, по которой важно использовать асинхронное программирование, когда наше приложение полагается на внешние службы, заключается в том, чтобы разрешить ASP.NET использовать порты завершения ввода-вывода, чтобы вместо того, чтобы блокировать поток, ожидающий ответа внешней службы, ASP.NET может запарковать выполнение в порту завершения ввода-вывода и использовать поток для обслуживания другого запроса, всякий раз, когда внешняя служба отвечает, тогда ASP.NET снова получает это выполнение и возобновляет его. Таким образом, ни один поток не блокируется.

Пример асинхронного метода:

[HttpPost]
public async Task<ActionResult> Open(String key)
{
    Foo foo= await _externalService.GetFoo(key);
    return View(foo);
}

Но что произойдет, если мы будем использовать несколько запросов к внешним сервисам? Как с этим справляется ASP.NET?

[HttpPost]
public async Task<ActionResult> Open()
{
    List<Task<Foo>> tasks = new List<Task<Foo>>();

    foreach (var key in this.Request.Form.AllKeys)
        tasks.Add(_externalService.GetFoo(key));

    var foos = await Task.WhenAll(tasks);

    Foo foo = null;
    foreach (var f in foos)
    {
        if (foo == null && f != null)
            foo = f;
        else
            foo.Merge(f);
    }
    return View(foo);
}

Он все еще использует порты завершения ввода-вывода? Или потому, что Task.WhenAll блокирует поток?


person vtortola    schedule 28.01.2014    source источник


Ответы (1)


Он по-прежнему использует порты завершения ввода-вывода. WhenAll является асинхронным и не блокирует поток.

person Stephen Cleary    schedule 28.01.2014
comment
Я редактировал вопрос. Он не блокирует поток, но блокирует ли он какой-либо поток? Я имею в виду, насколько я понимаю, порты завершения ввода-вывода позволяют вам припарковать задачу, не блокируя поток, поскольку существует связанная операция ввода-вывода. Но как это работает в случае с «WhenAll»? - person vtortola; 29.01.2014
comment
WhenAll - это просто TaskCompletionSource со счетчиком. Когда вы его вызываете, он устанавливает счетчик на количество задач и прикрепляет продолжение к каждой задаче, которая уменьшает счетчик. Когда счетчик достигает нуля, TCS завершается, что позволяет продолжить ваш метод. Никакие потоки не заблокированы. - person Stephen Cleary; 29.01.2014