我有一个应用程序接收某些“事件”,由12个字符串和一个DateTime唯一标识。在每个事件处关联一个字符串的结果。 我需要将这些事件保存在内存中(例如最多8小时)并且能够,如果我第二次收到相同的事件,能够知道我已经收到它(在过去的8小时内) 。 存储的事件将少于1000。 我不能使用外部存储器,它必须在内存中完成。
我的想法是使用一个字典,其中键是一个由字符串和日期时间组成的类,该值是结果。
编辑:字符串本身(实际上是MAC地址)不能唯一地标识事件,它是MAC和日期时间,这两者组合是唯一的,这就是密钥必须由两者组成的原因。 应用程序是从客户端接收特定事件的服务器:客户端MAC和客户端日期时间(不能使用guid)在客户端上标记事件。 可能会发生客户端重新传输相同的数据,并通过检查字典中的MAC / Datetime密钥,我知道我已经收到了该数据。
然后,每小时(例如),我可以预览整个集合并删除日期时间超过8小时的所有密钥。
您能否建议更好地解决问题或我选择的数据格式?在代码的性能和清洁方面。 或者更好的方法来删除旧数据,例如LINQ。
谢谢, 马蒂亚
答案 0 :(得分:1)
活动时间必须不成为密钥的一部分 - 如果是,您如何能够告诉您已经收到此活动?因此,您应该移动到一个字典,其中键是事件名称,值是日期和结果的元组。
偶尔你可以使用LINQ轻松修剪字典中的旧数据:
dictionary = dictionary
.Where(p => p.Value.DateOfEvent >= DateTime.Now.AddHours(-8))
.ToDictionary();
答案 1 :(得分:1)
如果要求声明每小时更新一次就足够了,并且字典中的项目从未超过1000个,那么您的解决方案应该是完全足够的,并且可能是其他任何查看您的代码的人最容易理解的。我可能会为键而不是类推荐不可变的结构,但就是这样。
如果立即删除而不是每小时一次有好处,你可以做一些事情,你也可以添加一个定时器,在8小时后删除它,但是你必须处理有线程安全和清理所有计时器等。可能不值得。
我会避免使用OrderedDictionary方法,因为它的代码更多,并且可能更慢,因为它必须为每个插入重新排序。
现在最常关注保持代码简单,只在必要时进行优化是一种常见的口头禅。在你有一个已知的瓶颈并对其进行分析之前,你永远不知道你是否正在优化正确的东西。 (根据你的描述,没有说明哪一部分在没有剖析的情况下会最慢)。
答案 2 :(得分:0)
我会使用OrderedDictionary,其中键是12个字符标识符,结果和日期时间是值的一部分。遗憾的是OrderedDictionary不是通用的(键和值是对象),因此您需要自己进行转换和类型检查。当您需要删除旧事件时,您可以通过OrderedDictionary进行操作,并在获得足够新的时间时停止。这假定您将它们添加到字典时按顺序使用的日期时间。
答案 3 :(得分:0)
我会去一本字典。
通过这种方式,您可以非常快速地搜索字符串(O(1) - 操作)。
其他收藏品较慢:
一个例子:
public class Event
{
public Event(string macAddress, DateTime time, string data)
{
MacAddress = macAddress;
Time = time;
Data = data;
}
public string MacAddress { get; set; }
public DateTime Time { get; set; }
public string Data { get; set; }
}
public class EventCollection
{
private readonly Dictionary<Tuple<string, DateTime>, Event> _Events = new Dictionary<Tuple<string, DateTime>, Event>();
public void Add(Event e)
{
_Events.Add(new Tuple<string, DateTime>(e.MacAddress, e.Time), e);
}
public IList<Event> GetOldEvents(bool autoRemove)
{
DateTime old = DateTime.Now - TimeSpan.FromHours(8);
List<Event> results = new List<Event>();
foreach(Event e in _Events.Values)
if (e.Time < old)
results.Add(e);
// Clean up
if (autoRemove)
foreach(Event e in results)
_Events.Remove(new Tuple<string, DateTime>(e.MacAddress, e.Time));
return results;
}
}