Vaughan Reid's blog

What is AyncLocal in C#?

An interesting class that is useful to know about but you most probably won’t directly use is AsyncLocal. It stores data local to the async flow. This means that if a method further down the chain changes the underlying value, the change will only apply to that and its children. A potential use case might be if you want to have access to a trace id on an internal request without having to manage some sort of cache.

I created an example to see it in action. I have a class that has a public method DoSomething that will call another method Run1 which will in turn call another method Run2.


public class AsyncLocalTesting
{
	AsyncLocal<int> _id = new AsyncLocal<int>();
	
	public async Task DoSomething()
	{
		_id.Value = 1;

		Console.WriteLine($"Main before Run1:{_id.Value}");
		await Run1();
		Console.WriteLine($"Main after Run1:{_id.Value}");
	}
	
	private async Task Run1()
	{
		Console.WriteLine($"Run1 start:{_id.Value}");
		_id.Value++;
		Console.WriteLine($"Run1 after increment:{_id.Value}");
		await Run2();
		Console.WriteLine($"Run1 after Run2:{_id.Value}");
	}

	private async Task Run2()
	{
		Console.WriteLine($"Run2 start:{_id.Value}");
		_id.Value++;
		Console.WriteLine($"Run2 after increment:{_id.Value}");
	}
}

Calling DoSomething outputs the following lines to the console.

Main before Run1:1
Run1 start:1
Run1 after increment:2
Run2 start:2
Run2 after increment:3
Run1 after Run2:2
Main after Run1:1

Whenever code is executing in DoSomething the value will be 1. That value gets passed on to Run1 which increments it. Run1 will always have the value as 2. Run2 increments it again and will now have the value as 3. After execution of Run2 the value is unchanged in Run1 and its also unchanged in DoSomething. A little interesting and hopefully might be useful to you one day!