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

Краткое объяснение Async/Await в .Net 4.5

Как работают асинхронные задачи (Async/Await) в .Net 4.5?

Пример кода:

private async Task<bool> TestFunction()
{
  var x = await DoesSomethingExists();
  var y = await DoesSomethingElseExists();
  return y;
}

Выполняется ли выполнение второго оператора await сразу или после возвращения первого await?

4b9b3361

Ответ 2

Выполняется после возвращения первого ожидания. Если эта вещь вас смущает, попробуйте поиграть с контрольными точками - они полностью поддерживаются новым шаблоном асинхронизации.

Представьте, что это будет выглядеть так:

var x = await GetSomeObjectInstance();
var y = await GetSomeObjectInstance2(x);

Вероятно, где-то возникло бы исключение NullReferenceException, поэтому первое ожидание должно вернуться первым. В противном случае x будет иметь значение null/undefined или что-то еще.

Ответ 3

Вызов методов будет по-прежнему происходить последовательно, как "обычные", не ожидаемые вызовы методов. Целью ожидания является то, что он вернет текущий поток в пул потоков, в то время как ожидаемая операция убежит и что-то делает.

Это особенно полезно в средах с высокой производительностью, например, на веб-сервере, где данный запрос обрабатывается в данном потоке из общего пула потоков. Если мы этого не ожидаем, то данный поток, обрабатывающий запрос (и все его ресурсы), остается "в использовании", пока завершается вызов db/service. Это может занять несколько секунд или более, особенно для внешних вызовов службы.

Теперь на сайтах с низким трафиком это не очень проблема, но на сайтах с высоким трафиком стоимость всех этих потоков запросов просто сидит, ничего не делая, в состоянии "в использовании", ожидая других процессов, таких как db/служебные вызовы для возврата могут быть бремени ресурсов.

Нам лучше отпустить поток обратно в рабочий пул, чтобы он мог выполнять другую полезную работу для другого запроса.

Как только вызов db/service завершается, мы можем прервать пул потоков и попросить поток продолжить обработку этого запроса с того места, где он был остановлен. В этот момент состояние запроса перезагружается и вызов метода продолжается.

Таким образом, на основе запроса при использовании ждут, запрос будет по-прежнему занимать одинаковое количество времени с точки зрения пользователей... плюс крошечный smidge больше для накладных расходов на переключение.

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

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