Just if someone has the same question some years later and finds this thread...
There is a new feature called
AsyncLocal<T>
https://learn.microsoft.com/en-us/dotnet/api/system.threading.asynclocal-1?view=netcore-3.1
This works with "async/await" and also with:
- Task.Run(...)
- Dispatcher.BeginInvoke(...)
- new Thread(...).Start()
I just testet those three with the following code:
private void StartTests() {
Thread.Sleep(1000);
Task.Run(() => DoWork1());
Task.Run(() => DoWork2());
}
private void DoWork1() {
ThreadContext.Context.Value = "Work 1";
Thread.Sleep(5);
Task.Run(() => PrintContext("1"));
Thread.Sleep(10);
Dispatcher.BeginInvoke(new Action(() => PrintContext("1")));
Thread.Sleep(15);
var t = new Thread(() => PrintContextT("1"));
t.Start();
}
private void DoWork2() {
ThreadContext.Context.Value = "Work 2";
Task.Run(() => PrintContext("2"));
Thread.Sleep(10);
Dispatcher.BeginInvoke(new Action(() => PrintContext("2")));
Thread.Sleep(10);
var t = new Thread(() => PrintContextT("2"));
t.Start();
}
private void PrintContext(string c) {
var context = ThreadContext.Context.Value;
Console.WriteLine("P: " + context + "-" + c);
Task.Run(() => PrintContext2(c));
}
private void PrintContext2(string c) {
Thread.Sleep(7);
var context = ThreadContext.Context.Value;
Console.WriteLine("P2: " + context + "-" + c);
}
private void PrintContextT(string c) {
var context = ThreadContext.Context.Value;
Console.WriteLine("T: " + context + "-" + c);
}
public class ThreadContext {
public static AsyncLocal<object> Context = new AsyncLocal<object>();
}
Output:
P: Work 2-2
P: Work 1-1
P2: Work 2-2
P: Work 2-2
P2: Work 1-1
P: Work 1-1
P2: Work 2-2
T: Work 2-2
P2: Work 1-1
T: Work 1-1
ThreadStatic
? You can flow your global state variables viaCallContext.LogicalSetData
/LogicalGetData
: https://mcmap.net/q/393834/-sharing-scope-across-awaits/1768303 – Menendezfoo.CallAsynx(context);
. That's the way ASP.NET MVC went. – Audition