我正在为以下场景搜索正确的线程安全集合(并发集合):
我可能有来自生成 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;
}
谢谢
最佳答案
您的实现存在缺陷,因为您确实使用了粒度为 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/