My understanding: GetAPIToken
is called and the current method (GetUser
) returns a Task<User>
object (which will provide a User object later). The current method's execution continues only once the GetAPIToken
method returns.
That is very close. Let's crisp that up in two ways.
First, let's make a distinction between returns -- which means, returns control to the caller -- and completes, which means the task represented by the method is completed and either we have its value, or, in the case of abnormal completion, an exception.
In non-async methods we do not need to make a distinction because returning control to the caller only happens on completion. In async methods, we can return-to-caller-as-suspension (because of awaiting a non-completed task) or return-as-completion (when the represented task is signalled as being complete).
Second, it is helpful to express the workflow in terms of what happens if the task is complete when it is created; this can happen in the case of caching, say.
So let's now re-state your understanding with that in mind:
GetAPIToken
is called and returns a task to the current user.
- If the task is completed, then GetApiToken returned when it finished all its work. GetUser extracts the token from the completed task and continues without suspending.
- If the task is not completed, and this is the first await in GetUser, then GetUser creates a
Task<User>
GetUser
assigns the remainder of GetUser
as the continuation of the Task<Token>
, and suspends by returning the Task<User>
- When the
Task<Token>
completes it runs its continuation, which resumes GetUser
where it left off.
what is the type/value of token while the code waits for the GetAPIToken() method to return?
Well, what would the value of token
be in an equivalent non-async case? Consider:
Token x = Foo();
What's the value of x while we're waiting for Foo to complete? Making Foo async doesn't make a difference; the local is not assigned a value until after the call completes normally. If Foo goes into an infinite loop, or if Foo throws, then x
is never assigned.
In practice of course, C# assigns all locals their default value when they are created, so that's the value that will be in the variable.