async/await

await is an asynchronous wait:

await operation();

The operation called after the await keyword is an “awaitable”. When execution reaches await:

  • if the awaitable operation has already completed, execution proceeds to the next statement in the containing method (like any normal synchronous operation);
  • if the awaitable operation has not already completed, the containing method returns. The rest of the method is executed as soon as the awaitable has completed.

Methods containing await must:

  • return an awaitable expression type or void (void only really makes sense in fire-and-forget notification/event handling scenarios);
  • be flagged async in method signature – this indicates to the compiler (and to human readers) that the method contains an await. (This also removes ambiguity by preventing the await keyword from being used as an identifier in the body of an async method – elsewhere it acts as any other identifier).

An expression is awaitable if it is of a type that provides a specific set of properties.

The types Task and Task<T> are awaitable; you could also roll your own.

If you don't need a result immediately (so can call an operation asynchronously) but will need it by some future time, Task.Wait() is a blocking call that returns only when the asynchronous operation has completed.

Task<T> enables you to return a value (of type T) from an async method. The Task wrapper provides a reference to the awaited operation, allowing you to access the returned value when the asynchronous operation has completed.

Access to the returned value is provided by the Task.Result property; calling the property's get accessor also blocks the calling thread (equivalent to calling Task.Wait()).