Является ли Async await ключевым словом, эквивалентным лямбде ContinueWith? - PullRequest
79 голосов
/ 07 января 2012

Может ли кто-нибудь проявить любезность, чтобы подтвердить, правильно ли я понял ключевое слово Async await? (С использованием версии 3 ОСАГО)

До сих пор я выяснил, что вставка ключевого слова await перед вызовом метода, по сути, делает 2 вещи: A. Он создает немедленный возврат и B. Он создает «продолжение», которое вызывается после завершения асинхронного метода. призывание. В любом случае продолжение является остатком блока кода для метода.

Итак, что меня интересует, так это то, что эти два бита кода технически эквивалентны, и если да, то означает ли это, что ключевое слово await идентично созданию ContinueWith Lambda (т. Е. Это, по сути, ярлык компилятора для одного)? Если нет, в чем различия?

bool Success =
    await new POP3Connector(
        "mail.server.com", txtUsername.Text, txtPassword.Text).Connect();
// At this point the method will return and following code will
// only be invoked when the operation is complete(?)
MessageBox.Show(Success ? "Logged In" : "Wrong password");

VS

(new POP3Connector(
    "mail.server.com", txtUsername.Text, txtPassword.Text ).Connect())
.ContinueWith((success) =>
    MessageBox.Show(success.Result ? "Logged In" : "Wrong password"));

Ответы [ 2 ]

80 голосов
/ 07 января 2012

Общая идея верна - оставшаяся часть метода превращена в продолжение сортов.

В блоге "fast path" есть подробности о том, как работает преобразование async / await.

Различия, вне моей головы:

Ключевое слово await также использует концепцию "контекста планирования". Контекст планирования - SynchronizationContext.Current, если он существует, возвращаясь к TaskScheduler.Current. Затем продолжение запускается в контексте планирования. Таким образом, более близкое приближение должно было бы передать TaskScheduler.FromCurrentSynchronizationContext в ContinueWith, возвращаясь к TaskScheduler.Current, если необходимо.

Фактическая реализация async / await основана на сопоставлении с образцом; он использует «ожидаемый» шаблон, который позволяет ожидать других вещей, помимо задач. Некоторыми примерами являются асинхронные API WinRT, некоторые специальные методы, такие как Yield, наблюдаемые Rx и специальные ожидаемые сокеты , которые не попадают в GC так сильно, как . Задачи являются мощными, но они не единственные ожидаемые.

На ум приходит еще одно незначительное различие: если ожидаемое уже завершено, то метод async фактически не возвращается в этот момент; это продолжается синхронно. Это похоже на передачу TaskContinuationOptions.ExecuteSynchronously, но без проблем, связанных со стеком.

8 голосов
/ 07 января 2012

Это «по сути», но сгенерированный код делает не только это. Для получения более подробной информации о сгенерированном коде я настоятельно рекомендую серию Eduasync Джона Скита:

http://codeblog.jonskeet.uk/category/eduasync/

В частности, пост № 7 посвящен тому, что генерируется (начиная с CTP 2) и почему, поэтому, вероятно, отлично подходит для того, что вы ищете в данный момент:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

РЕДАКТИРОВАТЬ: Я думаю, что это, вероятно, будет более подробно, чем то, что вы ищете из вопроса, но если вам интересно, как все выглядит, когда у вас есть несколько ожидает в методе, это описано в посте № 9: )

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/

...