несколько параллельных асинхронных вызовов с ожиданием - PullRequest
37 голосов
/ 12 мая 2011

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

    await someCall();
    await anotherCall();

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

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

Ответы [ 3 ]

50 голосов
/ 30 августа 2011

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;
6 голосов
/ 19 января 2012

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

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

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

var result = await taskA + await taskB;

, поэтому вам не нужно делать taskA.Result.

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

2 голосов
/ 26 марта 2014

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;
...