C# 这是ConcurrentDictionary线程安全的吗?

C# 这是ConcurrentDictionary线程安全的吗?,c#,C#,这是ConcurrentDictionary线程安全吗 private static ConcurrentDictionary<string, DateTime> dictionary= new ConcurrentDictionary<string, DateTime>(); public bool TextInputRecently(string text) { dictionary = new ConcurrentDicti

这是ConcurrentDictionary线程安全吗

    private static ConcurrentDictionary<string, DateTime> dictionary= new ConcurrentDictionary<string, DateTime>();

    public bool TextInputRecently(string text)
    {
        dictionary = new ConcurrentDictionary<string, DateTime>( dictionary.Where(pair => pair.Value.Ticks >= DateTime.Now.AddMinutes(-5).Ticks)
                             .ToDictionary(pair => pair.Key,
                                           pair => pair.Value));

        if (dictionary.ContainsKey(text))
            return true;

        dictionary.TryAdd(text, DateTime.Now);
        return false;
    }
私有静态ConcurrentDictionary=新ConcurrentDictionary();
公共布尔文本输入最近(字符串文本)
{
dictionary=new ConcurrentDictionary(dictionary.Where(pair=>pair.Value.Ticks>=DateTime.Now.AddMinutes(-5).Ticks)
.ToDictionary(pair=>pair.Key,
pair=>pair.Value));
if(字典.容器(文本))
返回true;
TryAdd(text,DateTime.Now);
返回false;
}
我认为这不是因为字典可以重新创建,而另一个线程正在检查密钥是否存在


我是否最好在字典中循环删除过时的值?

否;字典可以在
ContainsKey()
TryAdd()
之间更改

ConcurrentDictionary
上,不应连续调用两个方法,除非您确定不在乎它们之间是否发生变化。
类似地,您不能在字典中循环,因为它可能在循环过程中发生变化

相反,您应该使用更复杂的方法(如
TryAdd()
),它将检查并添加到单个原子操作中


此外,正如您所建议的,可能会替换整个词典。

否;词典可能会在
ContainsKey()
&
TryAdd()
之间更改

ConcurrentDictionary
上,不应连续调用两个方法,除非您确定不在乎它们之间是否发生变化。
类似地,您不能在字典中循环,因为它可能在循环过程中发生变化

相反,您应该使用更复杂的方法(如
TryAdd()
),它将检查并添加到单个原子操作中


此外,正如您所建议的,整个词典可能会被替换。

谢谢您的回答

我遵循了Scott Hannen的建议,并用MemoryCache替换了它


可能有更好的解决方案,但这适合我的需要。

谢谢你的回答

我遵循了Scott Hannen的建议,并用MemoryCache替换了它


可能有更好的解决方案,但这适合我的需要。

也许你要找的是缓存,比如
MemoryCache
。它是线程安全的,可以处理过期问题,因此你不必检查条目的日期或“手动”删除过期条目。可能您正在寻找的是缓存,如
MemoryCache
。它是线程安全的,可以处理过期问题,因此您不必检查条目的日期或“手动”删除过期条目。
private static MemoryCache cache;
    static readonly object cacheLock = new object();
    private int expiry_timeout = 5;

    public bool TextInputRecently(string text)
    {
        //Returns null if the string does not exist, prevents a race condition where the cache invalidates between the contains check and the retrieval.
        var cachedString = MemoryCache.Default.Get(text, null) as string;

        if (cachedString != null)
            return true;

        lock (cacheLock)
        {
            //Check to see if anyone wrote to the cache while we where waiting our turn to write the new value.
            cachedString = MemoryCache.Default.Get(text, null) as string;

            if (cachedString != null)
                return true;

            //The value still did not exist so we now write it in to the cache.                
            CacheItemPolicy cip = new CacheItemPolicy()
            {
                AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddSeconds(expiry_timeout))
            };
            MemoryCache.Default.Set(text, "", cip);
            return false;
        }
    }