c# - Correct Concurrent Collection 存储定时非循环结构

标签 c# c#-4.0 collections concurrency

我正在为以下场景搜索正确的线程安全集合(并发集合):

我可能有来自生成 GUID 的外部源的请求(因此它是唯一且非重复的)。我需要存储(比如最近的 100 个请求)并检查是否交付了重复的 GUID。由于某些限制,我可能无法保存超过 100 个左右的所有 GUID。

现在的问题是,当这个机制用在一个服务中时,它必须绑定(bind)100个项目,并且基于GUID的搜索是至关重要的。

我决定使用 ConcurrentDictionary 但我怀疑这是一个好的决定,因为我可能会在使用完 100 个插槽后更改 key 。我可能会找到一个很好的机制来在字典满时替换最旧的请求。

非常感谢任何想法。

提供了一个代码片段来展示我不完整的实现

public static ConcurrentDictionary<string, TimedProto> IncidentsCreated = new ConcurrentDictionary<string, TimedProto>(20, 100);

    private static bool AddTo_AddedIncidents(proto ReceivedIncident)
    {
        try
        {
            int OldestCounter = 0;
            DateTime OldestTime = DateTime.Now;

            if (IncidentsCreated.Count < 100)
            {
                TimedProto tp = new TimedProto();
                tp.IncidentProto = ReceivedIncident;
                tp.time = DateTime.Now;
                IncidentsCreated.AddOrUpdate(ReceivedIncident.IncidentGUID,  tp,
                    (s,i) => i);
                return true;
            }
            else //array is full, a replace oldest mechanism is required
            {

            }
            return true;
        }
        catch (Exception ex)
        {
            LogEvent("AddTo_AddedIncidents\n"+ex.ToString(), EventLogEntryType.Error);
            return false;
        }
    }


public struct proto
{
    public string IncidentGUID;
    //other variables
}

public struct TimedProto
{
    public proto IncidentProto;
    public DateTime time;
}

谢谢

最佳答案

试试这个:http://ayende.com/blog/162529/trivial-lru-cache-impl?key=02e8069c-62f8-4042-a7d2-d93806369824&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+AyendeRahien+%28Ayende+%40+Rahien%29

您的实现存在缺陷,因为您确实使用了粒度为 15 毫秒的 DateTime。这意味着如果您的流量很高,您甚至可能会不小心删除最近的 guid。

public class LruCache<TKey, TValue>
{
    private readonly int _capacity;
    private readonly Stopwatch _stopwatch = Stopwatch.StartNew();

    class Reference<T> where T : struct
    {
   public T Value;
    }

    private class Node
    {
        public TValue Value;
        public volatile Reference<long> Ticks;
    }

    private readonly ConcurrentDictionary<TKey, Node> _nodes = new ConcurrentDictionary<TKey, Node>();

    public LruCache(int capacity)
    {
        Debug.Assert(capacity > 10);
        _capacity = capacity;
    }

    public void Set(TKey key, TValue value)
    {
        var node = new Node
        {
            Value = value,
            Ticks = new Reference<long> { Value = _stopwatch.ElapsedTicks }
        };

        _nodes.AddOrUpdate(key, node, (_, __) => node);
        if (_nodes.Count > _capacity)
        {
            foreach (var source in _nodes.OrderBy(x => x.Value.Ticks).Take(_nodes.Count / 10))
            {
                Node _;
                _nodes.TryRemove(source.Key, out _);
            }
        }
    }

    public bool TryGet(TKey key, out TValue value)
    {
        Node node;
        if (_nodes.TryGetValue(key, out node))
        {
            node.Ticks = new Reference<long> {Value = _stopwatch.ElapsedTicks};
            value = node.Value;
            return true;
        }

        value = default(TValue);
        return false;
    }
}

关于c# - Correct Concurrent Collection 存储定时非循环结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17377578/

相关文章:

C# 替代标准 Treeview?

.net - 如何保持 DataGridRow 焦点和选择同步?

c# - 如何将大的 foreach 循环分解为批处理并同时处理?

java - Castor 自定义集合字段处理程序

c# - 在 ASP.NET Core 中使用 Enums 发送 Json post 请求时出现问题

c# - FileInfo.GetFiles() 和特殊字符(重音符号)

c# - 请求被中止 : The request was canceled. 没有解决方案

c# - 使用 C# 设计模式

dictionary - 为什么在 Clojure 的 transient 映射中插入 1000 000 个值会生成一个包含 8 个项目的映射?

仅针对添加(插入)操作优化的 Java 集合