Question

Trying to use new C# 5 async model it was surprising to me AspNetSynchronizationContext is an internal class (as well as AspNetSynchronizationContextBase base). Thus undocumented. But it's essential to know what it does when utilizing async/await feature within your ASP.NET code. Am I correct that It does guarantee your continuations will get the same HttpContext.Current as original callers? It does not guarantee the continuations will execute on the same thread as the callers?

If the latter assumption is not true and I get the original thread can I be sure to get the same thread context in continuations? I mean principal/culture associated with the thread and thread local storage? That's important because ASP.NET localization relies on thread's culture and my application relies on .NET role security model (thread's principal).

Was it helpful?

Solution

Am I correct that It does guarantee your continuations will get the same HttpContext.Current as original callers? It does not guarantee the continuations will execute on the same thread as the callers?

Yes, HttpContext.Current is preserved, and yes, the continuations may execute on a different thread.

I mean principal/culture associated with the thread and thread local storage? That's important because ASP.NET localization relies on thread's culture and my application relies on .NET role security model (thread's principal).

Ordinary thread-local storage is lost. You can mitigate this by using LogicalCallContext (which flows with ExecutionContext), but with async it's easier to just reference the variables directly.

Principal is always preserved; to do otherwise would be a security risk. This flows with ExecutionContext.

I believe that culture flows with AspNetSynchronizationContext, but I haven't tested this out on .NET 4.5's new implementation.


You may find my MSDN article on SynchronizationContext helpful. It's not official documentation (I don't work for Microsoft), but at least it's something. Note that the AspNetSynchronizationContext referenced in that article is now called LegacyAspNetSynchronizationContext in .NET 4.5.

Another great resource is Stephen Toub's ExecutionContext vs. SynchronizationContext.

OTHER TIPS

Well, while capturing the ExecutionContext is always guaranteed, capturing and running the execution on the same SynchronizationContext depends on the Awaiter.

The most common awaiter (the type returned by GetAwaiter() method that's internally called when you "await" something) is TaskAwaiter that returned by Task.GetAwaiter(). By default, TaskAwaiter will capture the current SynchronizationContext and run the continuation delegate on the captured SynchronizationContext. Which means, you'll be able to use HttpContext.Current in the rest of your method, and you don't mind that it'll run as a continuation. So, this code will works as expected (the part where you writes "B" will run on the same synchronizationcontext as the first line):

HttpContext.Current.Response.Write("A");
await Task.Delay(1000);
HttpContext.Current.Response.Write("B")

You can change this behavior by using Task.ConfigureAwait(false) method, that tells the awaiter to not marshal the rest of the method back to the original SynchronizationContext.

Of course, if you use Task.Run or Task.Factory.StartNew in the async method you're calling, it's your responsibility to capture the SynchronizationContext again.

Best of luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top