如何确定是否存在NamedDataSlot的最佳方法?

4
实际上,我想出了以下实现方式。
bool DoesNamedDataSlotsExist(string name)
{
    try
    {
        Thread.AllocateNamedDataSlot(name);
    }
    catch
    {
        return true;
    }
    return false;
}

这里显而易见的问题是:如果某个代码两次调用DoesNamedDataSlotExist(),它将会先生成false,然后再生成true(如果使用Thread.FreeNamedDataSlot()则可以进行优化……)。但有更好的方法吗?
编辑: GetNamedDataSlot的来源。
public LocalDataStoreSlot GetNamedDataSlot(string name)
{
    LocalDataStoreSlot slot2;
    bool tookLock = false;
    RuntimeHelpers.PrepareConstrainedRegions();
    try
    {
        Monitor.ReliableEnter(this, ref tookLock);
        LocalDataStoreSlot slot = (LocalDataStoreSlot) this.m_KeyToSlotMap[name];
        if (slot == null)
        {
            return this.AllocateNamedDataSlot(name);
        }
        slot2 = slot;
    }
    finally
    {
        if (tookLock)
        {
            Monitor.Exit(this);
        }
    }
    return slot2;
}

我需要访问this.m_KeyToSlotMap


你真的需要NamedDataSlots吗?文档中说:“为了更好的性能,使用带有ThreadStaticAttribute属性标记的字段。” - Albin Sunnanbo
1个回答

3
您可以在GetNamedDataSlot源代码中观察到的行为进行复制。
您可以引入一个特殊的实体,例如线程本地存储适配器,它将维护已分配数据槽的字典。所有数据槽的分配都应通过此实体进行。
这就是我的意思。
internal static class TLSAdapter
{
    static Dictionary<string, LocalDataStoreSlot> tlsSlots = new Dictionary<string, LocalDataStoreSlot>();

    public static bool DoesNamedDataSlotsExist(string name)
    {
        lock(tlsSlots)
        {
            return tlsSlots.ContainsKey(name);
        }

    }

    public static LocalDataStoreSlot AllocateNamedDataSlot (string name)
    {
        lock(tlsSlots)
        {
            LocalDataStoreSlot slot = null;
            if ( tlsSlots.TryGetValue(name, out slot) )
                return slot;

            slot = Thread.GetNamedDataSlot(name);
            tlsSlots[name] = slot;
            return slot;            
        }       
    }   
}

真棒!不过...你忘记了一件事:由于你将LocalDataStoreSlot存储在字典中,它将永远不会被垃圾回收...你应该给私有字典添加ThreadStatic属性,问题解决!使用ThreadStatic还意味着你可以在没有任何锁的情况下完成整个分配/检查的过程! - user57508
如果将私有字典标记为ThreadStatic,则每个线程都将拥有自己的实例,因此如果一个线程分配了一个插槽,则其他线程无法知道它(它将具有其单独的字典实例)。要使这些插槽可由GC收集,请向TLSAdapter添加删除方法。 - Vadym Stetsiak
啊...抱歉...实际上我的需求有点变化,而且“如果私有字典被标记为ThreadStatic,则每个线程都将拥有自己的实例”正是我想要的 :) ...无论如何...是的! - user57508

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接