Несколько ожиданий против Task.WaitAll - эквивалентно?
Что касается производительности, будут ли эти два метода работать параллельно GetAllWidgets()
и GetAllFoos()
?
Есть ли какая-то причина использовать один над другим? Кажется, что происходит много сцене с компилятором, поэтому я не понимаю.
============= МетодА: Использование нескольких ожиданий ==================================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
=============== МетодB: Использование Task.WaitAll =====================
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
Task.WaitAll(new List[] {getAllWidgetsTask, getAllFoosTask});
customer.Widgets = getAllWidgetsTask.Result;
customer.Foos = getAllFoosTask.Result;
return Ok(customer);
}
=====================================
Ответы
Ответ 1
Первая опция не будет выполнять две операции одновременно. Он выполнит первый и ждет его завершения, и только после этого второй.
Второй вариант будет выполняться одновременно, но будет ждать их синхронно (т.е. блокируя поток).
Вы не должны использовать обе опции, так как первая выполняется медленнее второй, а вторая блокирует поток без необходимости.
Ожидайте обе операции асинхронно с Task.WhenAll
:
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
await Task.WhenAll(getAllWidgetsTask, getAllFoosTask);
customer.Widgets = await getAllWidgetsTask;
customer.Foos = await getAllFoosTask;
return Ok(customer);
}
Обратите внимание, что после Task.WhenAll
завершена выполнение обеих задач, которые уже завершены, поэтому их ожидание немедленно завершается.
Ответ 2
Короткий ответ: Нет.
Task.WaitAll
блокирует, await
возвращает задачу, как только она встречается, и регистрирует оставшуюся часть функции и продолжения.
Метод ожидания "массового", который вы искали, Task.WhenAll
, который фактически создает новый Task
, который заканчивается, когда выполняются все задачи, переданные функции.
Так же: await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
Это для блокирующего вопроса.
Также ваша первая функция не выполняет обе функции параллельно. Чтобы заставить это работать с await
, вам нужно написать что-то вроде этого:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
Это сделает первый пример очень похожим на метод Task.WhenAll
.
Ответ 3
Только ваш второй вариант будет запускать их параллельно. Ваш первый будет ждать каждого вызова в последовательности.
Ответ 4
Как только вы вызовете метод async, он начнет выполнение. Будет ли он выполняться в текущем потоке (и, следовательно, запускается синхронно) или он будет работать async, определить невозможно.
Таким образом, в первом примере первый метод начнет работу, но затем вы искусственно прекратите поток кода с ожиданием. И, таким образом, второй метод не будет вызываться до того, как будет выполнен первый.
Второй пример вызывает оба метода без остановки потока с ожиданием. Таким образом, они потенциально будут работать параллельно, если методы являются асинхронными.