Replies: 2 comments
-
public async Task FuncAsync()
{
await Task.WhenAll(FooAsync(), BarAsync());
// What is the value?
Console.WriteLine(_asyncLocal.Value);
}
private async Task FooAsync()
{
await Task.Yield();
_asyncLocal.Value = "Hello from FooAsync";
}
private async Task BarAsync()
{
await Task.Yield();
_asyncLocal.Value = "Hello from BarAsync";
} If you are willing to tolerate the risks of such a system, you could create your own by wrapping the value in a |
Beta Was this translation helpful? Give feedback.
-
Hence this suggestion
I'm actually writing a test framework so it's users I'm trying to help out here. It's their code, and that's not a solution if using things like asp net which uses AsyncLocal in places under the hood |
Beta Was this translation helpful? Give feedback.
-
AsyncLocal is a really powerful tool, and is great for allowing static access to contextual information.
However it has its nuances and pitfalls.
Correct me if I'm wrong, but currently, AsyncLocal can only be set within a parent async method, and descendants of that method can access those AsyncLocal values.
The reverse is not possible, you cannot set an AsyncLocal value in a child and retrieve it in the parent.
And the same for sibling methods.
If possible, it would be powerful to provide an object such as
AsyncLocalContext
that would allow setting values in other places as if it was set in the parent. The context could be generated by the parent, and then passed wherever to set values as if the parent set them.If you don't want to share the context, then by not generating an object to be passed around, it should behave exactly as it does today.
I believe this could lead to more powerful and complex usages that could drive frameworks and such.
I'm imagining an API like this:
Usage example for a test framework:
I'm writing TUnit, a testing framework, and it's not uncommon for users to want to interact with AsyncLocals, especially if they're wanting to use Asp.Net etc. with Activities, or HttpContextAccessor.
I could expose this context to users, giving them the freedom to set values wherever if they so wish.
Currently as a workaround I have to have my parent method execute any 'set up hooks', and they have to be Synchronous void methods so they inherit the parent context, leading to an overly complex and ugly method, and if I was to refactor it into separate method calls, it'd break for users because they wouldn't be considered a parent method so they'd not be able to set the AsyncLocal values properly.
Example is here: https://github.com/thomhurst/TUnit/blob/cd4a9da54204aee3896d9ab17e53396249c642c1/TUnit.Engine/Services/SingleTestExecutor.cs#L94
If this is already possible someone please educate me! 😄
Beta Was this translation helpful? Give feedback.
All reactions