Is Async await keyword equivalent to a ContinueWith lambda?

The general idea is correct – the remainder of the method is made into a continuation of sorts.

The “fast path” blog post has details on how the async/await compiler transformation works.

Differences, off the top of my head:

The await keyword also makes use of a “scheduling context” concept. The scheduling context is SynchronizationContext.Current if it exists, falling back on TaskScheduler.Current. The continuation is then run on the scheduling context. So a closer approximation would be to pass TaskScheduler.FromCurrentSynchronizationContext into ContinueWith, falling back on TaskScheduler.Current if necessary.

The actual async/await implementation is based on pattern matching; it uses an “awaitable” pattern that allows other things besides tasks to be awaited. Some examples are the WinRT asynchronous APIs, some special methods such as Yield, Rx observables, and special socket awaitables that don’t hit the GC as hard. Tasks are powerful, but they’re not the only awaitables.

One more minor nitpicky difference comes to mind: if the awaitable is already completed, then the async method does not actually return at that point; it continues synchronously. So it’s kind of like passing TaskContinuationOptions.ExecuteSynchronously, but without the stack-related problems.

Leave a Comment