Подтвердить что ты не робот

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

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

    await someCall();
    await anotherCall();

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

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

4b9b3361

Ответ 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;