несколько параллельных асинхронных вызовов с ожиданием

#asynchronous #multitasking #async-await #c#-5.0

#асинхронный #многозадачность #асинхронный-ожидание #c #-5.0

Вопрос:

Насколько я знаю, когда среда выполнения сталкивается с приведенным ниже оператором, она оборачивает остальную часть функции как обратный вызов метода, который вызывается асинхронно ( someCall() в этом примере). В этом случае anotherCall() будет выполнен обратный вызов someCall() :

     await someCall();
    await anotherCall();
  

Интересно, возможно ли заставить среду выполнения работать следующим образом: вызывайте someCall() асинхронно и немедленно возвращайтесь к вызывающему потоку, затем вызывайте anotherCall() аналогично (не дожидаясь someCall завершения). Потому что мне нужно, чтобы эти два метода выполнялись асинхронно, и предположим, что эти вызовы просто запускают и забывают вызовы.

Возможно ли реализовать этот сценарий, используя только async и await (не используя старый механизм begin / end )?

Ответ №1:

Async / await включает в себя несколько операторов для облегчения параллельной композиции, таких как WhenAll и WhenAny .

 var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await

// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);

// Retrieve the results.
var resultA = taskA.Resu<
var resultB = taskB.Resu<
  

Комментарии:

1. Есть ли что-нибудь из этого для ECMAScript / Javascript?

2. @Azteca: Конечно, вы можете использовать Promise.all вместо Task.WhenAll или Promise.race вместо Task.WhenAny . Например., await Promise.all([promiseA, promiseB]);

Ответ №2:

Вероятно, самый простой способ сделать это:

 var taskA = someCall();
var taskB = someOtherCall();
await taskA;
await taskB;
  

Это особенно удобно, если вам нужны результирующие значения:

 var result = await taskA   await taskB;
  

так что вам не нужно делать taskA.Result .

TaskEx.WhenAll может быть быстрее, чем два ожидания друг за другом. я не знаю, поскольку я не проводил исследование производительности по этому поводу, но если вы не видите проблемы, я думаю, что два последовательных ожидания читаются лучше, особенно если вы хотите значения результата.

Комментарии:

1. Цитирую «Асинхронность в C # 5.0»: «Это опасный способ ожидания нескольких задач, если они могут вызывать исключения. Если обе операции генерируют исключение, первая await распространит свое исключение, что означает, что taskB никогда не ожидается. Его исключение не будет наблюдаться и, в зависимости от версии .NET и настроек, может быть потеряно или даже повторно подключено к неожиданному потоку, завершая процесс «.

2. Так что вам лучше придерживаться await Task.WhenAll(taskA, taskB);

Ответ №3:

Асинхронный CTP больше не нужен, если вы используете .NET 4.5. Обратите внимание, что функциональность async реализована компилятором, поэтому приложения .NET 4 могут ее использовать, но для ее компиляции требуется VS2012.

TaskEx больше не нужен. CTP не смог модифицировать существующую платформу, поэтому он использовал расширения для выполнения задач, которые язык мог бы обрабатывать в версии 5.0. Просто используйте Task напрямую.

Таким образом, я переписал код (на который ответил Стивен Клири), заменив TaskEx на Task .

 var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await

// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);

// Retrieve the results.
var resultA = taskA.Resu<
var resultB = taskB.Resu<