In a synchronous environment, it is easy to create a scoped context which allows you to attach out-of-band context to your current thread. Examples of this are the current TransactionScope or thread-static logging context.
using (new MyContext(5))
Assert.Equal(5, MyContext.Current);
Assert.Equal(null, MyContext.Current);
It is easy to implement the context using a combination of IDisposable and a thread-static field.
Obviously, this falls apart when using async methods, because the context is based on a thread-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 would also want that the context is passed to the async methods in the call chain, so this should work as well:
using (new MyContext(5))
{
Assert.Equal(5, MyContext.Current);
await AssertContextIs(5);
}
Does anyone have an idea how this could be implemented? Losing out-of-band context when using the async/await pattern makes some pieces of the code really ugly.
Think of async WebAPI calls where you would like to use request-based context for logging purposes. You want your logger deep in the call stack to be aware of the request ID without having the need to pass that request ID all the way through the call stack using parameters.
Thanks for any help!