How can we create a callcontext for async.net methods?

In a synchronous environment, it’s easy to create a context that allows you to attach an out-of-band context to the current thread. Examples of this are the current TransactionScope context or stream-static log.

using (new MyContext(5)) Assert.Equal(5, MyContext.Current); Assert.Equal(null, MyContext.Current); 

It is easy to implement context using a combination of IDisposable and a stream-static field .

Obviously, this is falling apart when using async methods because the context is based on a streaming static field. So this fails:

 using (new MyContext(5)) { Assert.Equal(5, MyContext.Current); await DoSomethingAsync(); Assert.Equal(5, MyContext.Current); } 

And, of course, we also want the context passed to the async methods in the call chain, so this should also work:

 using (new MyContext(5)) { Assert.Equal(5, MyContext.Current); await AssertContextIs(5); } 

Does anyone have an idea how this can be implemented? Losing out-of-band context when using the async / await pattern makes some pieces of code really ugly.

Think of async WebAPI calls where you want to use query-based context for logging. You want your registrar to be in the back of the call stack to know the request identifier, without having to pass that request identifier completely through the call stack using parameters.

Thanks for any help!

+1
source share
2 answers

The best solution is to use HttpContext.Current.Items in ASP.NET or IOwinRequest.[Get|Set] in OWIN. Yes, this means that the transfer of the request object occurs everywhere, which makes sense if you think that your "context value" refers to this request. If you are not comfortable using the "library" method, knowing about OWIN, then it's easy to write a "context wrapper" object and pass it instead.

However, if you are sure that you do not want to skip anything, you can use LogicalCallContext with immutable data , as I describe in my blog. If you're just worried about logging, then you may find my AsyncDiagnostics library useful - it uses PostSharp to enter method names, and you can add your own information to the async stack as well.

+5
source

If you are in a hosted environment (you are talking about WebAPI), you should use the request context ( HttpContext.Current ) and not a thread, since you do not control the flows and do not know when / if the original stream will be unavailable or how to return to it.

The request context is correctly processed using the await keyword.

0
source

All Articles