public static async Task AsyncMethodNotifications()
{
//
// Define thread-local and async-local values. The async-local value uses its notification
// to keep the thread-local value in sync with the async-local value.
//
ThreadLocal<int> tls = new ThreadLocal<int>();
AsyncLocal<int> als = new AsyncLocal<int>(args =>
{
tls.Value = args.CurrentValue;
});
Assert.Equal(tls.Value, als.Value);
als.Value = 1;
Assert.Equal(tls.Value, als.Value);
als.Value = 2;
Assert.Equal(tls.Value, als.Value);
await Run(async () =>
{
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 2);
als.Value = 3;
Assert.Equal(tls.Value, als.Value);
Task t = Run(async () =>
{
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 3);
als.Value = 4;
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 4);
await Task.Run(() =>
{
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 4);
als.Value = 5;
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 5);
});
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 4);
als.Value = 6;
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 6);
});
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 3);
await Task.Yield();
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 3);
await t;
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 3);
});
Assert.Equal(tls.Value, als.Value);
Assert.Equal(als.Value, 2);
}