如何防止任务继承父任务逻辑调用上下文
How to prevent task from inheriting parent task Logical Call context
在使用 Task.Run() 和 Async 方法时,我正在尝试使用 AsyncLocal 替代 Thread 本地存储。
我遇到的问题是我需要下面的代码来打印
from t1 t1
from t1 t1
from t2 t2
from t2 t2
如果使用 Thread 本地存储,这将是行为,但我得到了这个输出。
from t1 t1
from t1 t1
from t2 t1
from t2 t1
示例代码:
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();
}
}
我知道的唯一方法是使用 ThreadPool.UnsafeQueueUserWorkItem:
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 tcs = new TaskCompletionSource<bool>();
ThreadPool.UnsafeQueueUserWorkItem(async s =>
{
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);
((TaskCompletionSource<bool>)s).SetResult(true);
}, tcs);
await tcs.Task;
});
t1.Wait();
}
}
您可以在调用 Task.Run 之前抑制流并在
之后恢复它
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();
}
}
给予
from t1 t1
from t1 t1
from t2 t2
from t2 t2
在使用 Task.Run() 和 Async 方法时,我正在尝试使用 AsyncLocal 替代 Thread 本地存储。 我遇到的问题是我需要下面的代码来打印
from t1 t1
from t1 t1
from t2 t2
from t2 t2
如果使用 Thread 本地存储,这将是行为,但我得到了这个输出。
from t1 t1
from t1 t1
from t2 t1
from t2 t1
示例代码:
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();
}
}
我知道的唯一方法是使用 ThreadPool.UnsafeQueueUserWorkItem:
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 tcs = new TaskCompletionSource<bool>();
ThreadPool.UnsafeQueueUserWorkItem(async s =>
{
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);
((TaskCompletionSource<bool>)s).SetResult(true);
}, tcs);
await tcs.Task;
});
t1.Wait();
}
}
您可以在调用 Task.Run 之前抑制流并在
之后恢复它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();
}
}
给予
from t1 t1
from t1 t1
from t2 t2
from t2 t2