Let’s say I have an async method Task Parent()
that calls a synchronous method void Child()
. The Child()
method sets the value of some AsyncLocal. After Child()
returns the AsyncLocal value that was set by it is visible in the remainder of the Parent()
method and all other methods called by it.
Now if I change the void Child()
to Task Child()
and I await it in the Parent()
, the change made to the AsyncLocal is no longer visible to the Parent()
. This is expected as every async span gets an independent copy of the AsyncLocal context at creation time (actually it receives the original and a copy is made on first write) so the AsyncLocal that the Child()
is changing is actually an independent one. But what if I want the value to be retained?
I’m considering two options: One is to use a simple Box<T>
that would act as a pointer, so every async span gets the same box but the box content mutates; this works, but now the Parent() needs to be aware of the box (it needs to set it up before calling Child). The other option which I really want to use is to change the Child() so that it returns a Task<ExecutionContext>
via return ExecutionContext.Capture()
which the Parent() would simply restore after awaiting on Child(). This should restore all AsyncLocals without knowing them all.
I’m asking whether this second option is safe to use, is it the established way of solving this? Are there any gotchas, pitfalls or footguns that I should watch out for?
Note: The Parent is not aware of the AsyncLocal existing, other methods that the Parent calls after calling Child actually have access.
2