Understanding context in C# 5 async/await

asp.net-4.5, async-await, c#, conceptual, multithreading

Solution

Am i correct that async/await itself has nothing to do with concurrency/parallelism and is nothing more than CPS implementation?

Well, `async` / `await` is a rewriting that uses CPS, so your core understanding is correct.

Regarding "concurrency" and "parallelism", I would say that it does enable concurrency; you can start multiple `async` operations which are all "in flight" at the same time. This is easy to do with `Task.WhenAll` and `Task.WhenAny`.

Also, even though `async` by itself doesn't imply "multithreading", `Task.Run` does enable easy `async`-compatible multithreading

And the real threading is performed by SynchronizationContext instance that await passes/restores?

Think of it this way: the continuation created by the CPS rewriting has to run somewhere. The captured "async context" can be used to schedule the continuation.

Side note: the captured context is actually `SynchronizationContext.Current` unless it is null, in which case the captured context is `TaskScheduler.Current`.

Another important note: the capturing and restoring of the context is actually up to the "awaiter" object. So, by default, if you `await` a `Task` (or any other built-in awaitable), the context will be captured and restored. But if you `await` the result of `ConfigureAwait(false)`, then the context is not captured. Similarly, if you `await` your own custom awaitable, it won't capture the context (unless you program it to).

However, are there any guaranties that the thread's context information is persisted? I mean Name, CurrentPrincipal, CurrentCulture, CurrentUICulture, etc.

`SynchronizationContext` is different than `ExecutionContext`. A simplified answer is that `ExecutionContext` always "flows", so `CurrentPrincipal` flows (if it didn't, it could be a security issue, which is why APIs that don't flow `ExecutionContext` always end in `Unsafe`).

In UI apps, culture doesn't flow, but by default it's the same for all threads anyway. `Name` is definitely not going to flow, unless you resume on the same thread (e.g., using a UI `SynchronizationContext`).

For some further reading, I recommend starting with my own `async` / `await` tutorial and then the official `async` / `await` FAQ. Then take a look at Stephen Toub's blog post on `ExecutionContext` vs. `SynchronizationContext`.

You may also find my `SynchronizationContext` article helpful.

Problem

Am I correct that async/await itself has nothing to do with concurrency/parallelism and is nothing more than continuation-passing style (CPS) implementation? And the real threading is performed by `SynchronizationContext` instance that `await` passes/restores? If that is correct I have the following question about `SynchronizationContext`: it guarantees that a continuation will be executed on the same thread. However, are there any guaranties that the thread's context information is persisted? I mean `Name`, `CurrentPrincipal`, `CurrentCulture`, `CurrentUICulture`, etc. Does it depend on framework (ASP.NET, WinForms, WCF, WPF)?

Original source

Related problems