Что здесь делать? - PullRequest
       4

Что здесь делать?

0 голосов
/ 11 февраля 2019

С учетом сигнатуры метода:

(awaitable) Task<Token> ITokenService.GetAPIToken();

В этом методе происходит то, что происходит на линии с await?

public async Task<User> GetUser(string userId)
{
    Token token = await TokenService.GetAPIToken();

    //..........
}

Мое понимание: GetAPIToken вызывается итекущий метод (GetUser) возвращает объект Task<User> (который будет предоставлять объект User позже).Выполнение текущего метода продолжается только после возврата метода GetAPIToken.

Если я ошибаюсь, каков тип / значение token, пока код ожидает возврата метода GetAPIToken()?

Я понимаю, что результат вызова этого метода будет другим, учитывая, что он может быть вызван с ключевым словом await или без него.Пожалуйста, примите во внимание, что сообщение вызывается с await.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Мое понимание: GetAPIToken вызывается, и текущий метод (GetUser) возвращает объект Task<User> (который предоставит объект User позже).Выполнение текущего метода продолжается только после возврата метода GetAPIToken.

Это очень близко.Давайте разберемся с этим двумя способами.

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

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

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

Итак, давайте теперь переформулируем ваше понимание с учетом этого:

  • GetAPIToken вызывается и возвращает задачу втекущий пользователь.
  • Если задача завершена, то GetApiToken вернется после завершения всей своей работы.GetUser извлекает токен из выполненной задачи и продолжает работу без приостановки.
  • Если задача не выполнена, и это первое ожидание в GetUser, то GetUser создает Task<User>
  • GetUser присваивает остаток от GetUser как продолжение Task<Token> и приостанавливает, возвращая Task<User>
  • Когда Task<Token> завершается, он запускает свое продолжение, которое возобновляет GetUser, где он оставилoff.

Каков тип / значение токена, пока код ожидает возврата метода GetAPIToken ()?

Хорошо, каково значениеtoken в эквивалентном не асинхронном случае?Подумайте:

Token x = Foo();

Какое значение x, пока мы ждем завершения Foo?Создание асинхронного Foo не имеет значения;локальному не присваивается значение до тех пор, пока вызов обычно не завершится .Если Foo входит в бесконечный цикл, или если Foo бросает, то x никогда не назначается.

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

0 голосов
/ 11 февраля 2019

В строке с await, действительно, выполнение GetUser() останавливается (ожидает), пока не вернется GetAPIToken().Это правильно.Следовательно, token не имеет значения (или даже объявляется в этом случае), пока не получит его от возврата GetAPIToken().

То, что возвращает GetUser(), зависит от того, как оно вызывается, с await или без негооператор.Если вызывается с await, вызывающий GetUser() также будет ждать его завершения.Кроме того, в этом случае вызывающий в конечном итоге получит User, возвращаемый GetUser(), а не Task<User>.

В этом сценарии вы не выиграете от параллельного выполнения чего-либо.

Если, с другой стороны, GetUser() вызывается без оператора await, две вещи происходят по-разному: GetUser() возвращается вызывающему абоненту раньше, как только он фактически достиг вашей линии;и он возвращает Task<User> вместо User напрямую - после того, как ничего еще не было создано.

Из этого Task звонящий может позже (после выполнения других вещей параллельно, этовесь смысл) получим в итоге User.Это можно сделать разными способами;см. методы и свойства Task<>.

Важно понимать, когда все идет параллельно.В этом случае (если GetUser() был вызван без await), есть вероятность, что GetUser() вернется, и вы продолжите делать что-то, пока параллельно в другом потоке GetAPIToken() еще не вернулось, и поэтому tokenне инициализируется.

Посмотрите эту хорошую статью MSDN с графиком: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index#BKMK_WhatHappensUnderstandinganAsyncMethod

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...