Description
I'm not sure this is bug or by-design. Consider the following use case of AsyncLocal<T>. Should I expect stringLocal.Value to be "Test" or null?
var stringLocal = new AsyncLocal<string>();
async IAsyncEnumerable<int> IntSequence()
{
stringLocal.Value = "Test";
yield return 10;
// Now what should happen if we do not explicitly capture the execution context???
Console.WriteLine("stringLocal.Value: {0}", stringLocal.Value);
}
From what I can observe currently, stringLocal.Value after yield return is null.
Configuration
.NET 5 / .NET 6.0.100-preview.1.21103.9
Regression?
N / A
Other information
Here is an extensive test around the persistence of AsyncLocal<T>. [.NET Fiddle]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
var stringLocal = new AsyncLocal<string>();
async IAsyncEnumerable<int> IntSequence(string localValue)
{
stringLocal.Value = localValue;
Console.WriteLine("Set up stringLocal: {0}.", localValue);
await Task.Delay(100).ConfigureAwait(false);
// await didn't affect AsyncLocal flow
Console.WriteLine("stringLocal.Value: {0}", stringLocal.Value);
using var execContext = ExecutionContext.Capture();
Debug.Assert(execContext != null); // i.e. ExecutionContext.IsFlowSuppressed() == false
yield return 10;
ExecutionContext.Restore(execContext);
// This gives us the correct value, as we have restored execution context.
Console.WriteLine("stringLocal.Value: {0}", stringLocal.Value);
// Now what should happen if we do not explicitly capture the execution context???
yield return 20;
Console.WriteLine("stringLocal.Value: {0}", stringLocal.Value);
yield return 30;
Console.WriteLine("stringLocal.Value: {0}", stringLocal.Value);
}
async Task PrintSequence1()
{
await foreach (var i in IntSequence("value 1"))
{
Console.WriteLine("Sequence: {0}", i);
await Task.Delay(100);
}
}
async Task PrintSequence2()
{
await using var it = IntSequence("value 2").GetAsyncEnumerator();
while (await it.MoveNextAsync())
{
Console.WriteLine("Sequence: {0}", it.Current);
}
}
PrintSequence1().Wait();
Console.WriteLine();
PrintSequence2().Wait();
Here is the output
Set up stringLocal: value 1.
stringLocal.Value: value 1
Sequence: 10
stringLocal.Value: value 1
Sequence: 20
stringLocal.Value:
Sequence: 30
stringLocal.Value:
Set up stringLocal: value 2.
stringLocal.Value: value 2
Sequence: 10
stringLocal.Value: value 2
Sequence: 20
stringLocal.Value:
Sequence: 30
stringLocal.Value:
Description
I'm not sure this is bug or by-design. Consider the following use case of
AsyncLocal<T>. Should I expectstringLocal.Valueto be"Test"ornull?From what I can observe currently,
stringLocal.Valueafteryield returnisnull.Configuration
.NET 5 / .NET 6.0.100-preview.1.21103.9
Regression?
N / A
Other information
Here is an extensive test around the persistence of
AsyncLocal<T>. [.NET Fiddle]Here is the output