I am trying to use AsyncLocal as a replacement for Thread local storage when using Task.Run() and Async methods. The problem I have is that i need the code below to print
from t1 t1
from t1 t1
from t2 t2
from t2 t2
This would be the behavior if using Thread local storage, but instead I am getting this output.
from t1 t1
from t1 t1
from t2 t1
from t2 t1
Example code:
public class ClientClass {
public static void Main()
{
AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
var t1 = Task.Run( async () => {
string a = _asyncLocalString.Value;
if (a == null) {
_asyncLocalString.Value = "t1";
}
a = _asyncLocalString.Value;
Console.WriteLine("from t1 " + a);
await Task.Delay(10);
string b = _asyncLocalString.Value;
Console.WriteLine("from t1 " + b);
var t2 = Task.Run( async () => {
string aa = _asyncLocalString.Value;
if (aa == null) {
_asyncLocalString.Value = "t2";
}
aa = _asyncLocalString.Value;
Console.WriteLine("from t2 " + aa);
await Task.Delay(10);
string bb = _asyncLocalString.Value;
Console.WriteLine("from t2 " + bb);
});
await t2;
});
t1.Wait();
}
}
You can Suppress the flow prior to calling Task.Run and restore it after
public class ClientClass {
public static void Main()
{
AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
var t1 = Task.Run(async () =>
{
string a = _asyncLocalString.Value;
if (a == null)
{
_asyncLocalString.Value = "t1";
}
a = _asyncLocalString.Value;
Console.WriteLine("from t1 " + a);
await Task.Delay(10);
string b = _asyncLocalString.Value;
Console.WriteLine("from t1 " + b);
ExecutionContext.SuppressFlow();
var t2 = Task.Run(async () =>
{
string aa = _asyncLocalString.Value;
if (aa == null)
{
_asyncLocalString.Value = "t2";
}
aa = _asyncLocalString.Value;
Console.WriteLine("from t2 " + aa);
await Task.Delay(10);
string bb = _asyncLocalString.Value;
Console.WriteLine("from t2 " + bb);
});
ExecutionContext.RestoreFlow();
await t2;
});
t1.Wait();
}
}
Giving
from t1 t1
from t1 t1
from t2 t2
from t2 t2