Несколько параллельных асинхронных вызовов с ожиданием
Насколько я знаю, когда среда выполнения сталкивается с приведенным ниже оператором, она оборачивает оставшуюся часть функции в качестве обратного вызова метода, который вызывается асинхронно (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.Result;
var resultB = taskB.Result;
Ответ 2
Самый простой способ, вероятно, сделать это:
var taskA = someCall();
var taskB = someOtherCall();
await taskA;
await taskB;
Это особенно приятно, если вы хотите получить значения результата:
var result = await taskA + await taskB;
поэтому вам не нужно делать taskA.Result
.
TaskEx.WhenAll
может быть быстрее двух ожиданий друг за другом. я не знаю, так как я не проводил исследования по эффективности, но если вы не видите проблему, я думаю, что два последовательных ожидания читаются лучше, особенно если вы оцениваете значения результатов.
Ответ 3
Async CTP больше не нужен, если вы используете .NET 4.5. Обратите внимание, что асинхронная функциональность реализована компилятором, поэтому приложения .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.Result;
var resultB = taskB.Result;