在使用Task时,我正尝试使用AsyncLocal作为线程本地存储的替代品。Run((和Async方法。我的问题是我需要下面的代码来打印
from t1 t1
from t1 t1
from t2 t2
from t2 t2
如果使用线程本地存储,这将是一种行为,但我得到的却是这种输出。
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();
}
}
您可以在调用Task之前抑制流。后运行并恢复
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
我所知道的唯一方法是使用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();
}
}