.NET Core中的AsyncLocal<>,例如CallContext.LogicGetData/LogicSetDataGetDataSetData怎么样?Thread.GetData/SetDataThreadStaticThreadLocal都具有相同的问题,当Thread完成时,这些值将不干净,如果这些Thread重用(或可能是Thread Id重用),则LocalValue已经存在。

class Program
{
    [ThreadStatic]
    private static string Static;
    private static ThreadLocal<string> Local = new ThreadLocal<string>(false);
    private static LocalDataStoreSlot Slot = Thread.AllocateDataSlot();

    static void Main(string[] args)
    {
        var threadIds = new List<int>();
        for (var i = 0; i < 100; i++)
        {
            Task.Run(() =>
            {
                if (threadIds.Contains(Thread.CurrentThread.ManagedThreadId))
                {
                    if(Static == null || Local.Value == null || Thread.GetData(Slot) == null)
                    {
                        // never get in
                    }
                    else
                    {
                        // same thread id always already exists value
                    }
                }
                else
                {
                    threadIds.Add(Thread.CurrentThread.ManagedThreadId);
                    if (Static == null && Local.Value == null && Thread.GetData(Slot) == null)
                    {
                        var threadId = Thread.CurrentThread.ManagedThreadId.ToString();
                        Static = threadId;
                        Local.Value = threadId;
                        Thread.SetData(Slot, threadId);
                    }
                    else
                    {
                        //never get in
                    }
                }
            }).Wait();
        }

        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }
}

我知道CallContext的工作方式,它只是将LogicalCallContext值复制到子线程中,而不复制IllogicalCallContext。但是.NET Core仅在IAsyncLocalValueMap中添加了ExecutionContext,并且始终将其复制到子线程中(SuppressFlow除外)。那么,有没有GetData/SetData的实现?或完成后清除ThreadLocal的任何方法。

最佳答案

使用AsyncLocal的更改处理程序在线程更改时清除值吗?

private static AsyncLocal<string> AsyncLocal
    = new AsyncLocal<string>(ThreadContextChanged);

private static void ThreadContextChanged(AsyncLocalValueChangedArgs<string> changedArgs)
{
    if (changedArgs.ThreadContextChanged &&
        changedArgs.CurrentValue != null)
    {
        AsyncLocal.Value = null;
    }
}

10-08 14:32