2011-02-09 86 views
0

我想以有效的方式从队列中删除重复的条目。 队列与DateTime和FULLPATH和其他一些东西如何在一个时间范围内从队列中删除重复项目?

private Queue<MyCustomClass> SharedQueue; 

自定义类的日期时间在班上是时间戳,当插入到队列中。我想要使​​用的逻辑如下:如果FullPath在4秒钟内完全相同(即,如果在重复的完整路径的4秒内添加到队列中),则从队列中删除重复项。我有我想要观看的事件,但有一些重复的内容仍然会到达,这没关系。

我正在使用c#2.0和FileSystemWatcher类和一个工作队列。

有很多种方法可以做到这一点: 每次向其中添加项目时或者当我在队列上工作时,修剪队列跳过处理当前的重复项目。

或者我应该使用“全球私人”变量字典<字符串,日期时间>?所以我可以快速搜索它?或队列的本地副本?在许多文件事件的情况下,最好将本地队列限制为100个项目?虽然在我的情况下,它“应该是”只有相对较少的文件来监视的文件夹中...但事情总是变化......

感谢您的帮助。

:编辑:2月10日美国东部时间八点54: 所以我决定,据我可以告诉落实好简单的解决方案。 我不认为我坚持的字典键太长...

:编辑:2月10日9:53美国东部时间:更新为我的字典不能包含重复的值。

public void QueueInput(HotSynchUnit.RcdFSWFile rcd) 
// start the worker thread when program starts. 
// call Terminate.Set() in the programs exit routine or close handler etc. 
{ 
    // lock shared queue 
    lock (SharedQueue) 
    { 
    if (!IsDuplicateQueueInput(rcd)) // only add unique values to queue 
    { 
     SharedQueue.Enqueue(rcd); 
     SomethingToDo.Set(); 
    } 
    } 
} // public void QueueInput 

private bool IsDuplicateQueueInput(HotSynchUnit.RcdFSWFile rcd) 
/* Return true if the object is a duplicate object. 
* Pseudo Code: 
* 
* isDuplicate = false 
* Lock Dictionary 
* -If lastTimeStamp > 4 seconds ago then  // Optimization: save lastTimeStamp 
* if Dict.Count > 0 then clear Dictionary 
* return isDuplicate 
* -If not Dict.TryGetValue(sPath, dtTimeStamp) then 
* Dict.AddKey() 
* -Else 
* Compare key timestamp to Currenttime 
* if key timestamp is <= 4 seconds ago then 
*  IsDuplicate = True 
* 
* Dict.RemoveKey() 
* Dict.AddKey() 
* 
* return isDuplicate 
*/ 
{ 
    // put real code here 
} 
+1

为什么选择'全球私人'字典?为什么不把它放在与你的队列相同的范围? – recursive 2011-02-09 16:47:55

+0

这实际上是它在哪里。我的错。 – user610064 2011-02-09 17:29:41

+0

谢谢@StevenJeuris在Enqueue之前检查我的想法 - 我忘记了我在那里做了那个例程。我不想进入重写或扩展类... – user610064 2011-02-10 14:08:34

回答

1

我刚想过使用任何集合类似于通用散列表 ...事情是这样的:

Dictionary<string, YourClass> dict = new Dictionary<string, YourClass>(); 

/// just let's assume you want to add/check for "c:\demo.txt" 

if (!dict.ContainsKey(@"c:\demo.txt")) 
{ 
    /// add items to dict by passing fullPath as key and your objects as value 
    dict.add(@"c:\demo.txt", obj1); 
} 
else if (dict[@"c:\demo.txt"].CheckForIntervall()) 
{ 
    /// replace current object in dictionary with new object - in case you want to.. 
    /// or just do what you want to 
} 

编辑 - 自定义类可能有一些像这样的功能:

class YOURCUSTOMCLASS 
{ 
    private DateTime creationTime; 

    public DateTime CreationTime 
    { get { return creationTime; } } 

    public YOURCUSTOMCLASS(parametersGoesHere xyz) 
    { 
      creationTime = DateTime.Now; 
    } 

    /// in this case this method will return true 
    /// if the timeSpan between this object and otherObject 
    /// is greater than 4 seconds 
    public bool CheckForInterval(YOURCUSTOMCLASS otherObject) 
    { 
     TimeSpan diff = otherObj.CreationTime.Subtract(creationTime); 

     /// you may replace 4 through any other digit, or even better take 
     /// a const/global var/static ... 
     return diff.TotalSeconds > 4; 
    } 

    /// all the other stuff you need ... 
} 

你当然宽松队列的功能 - 但你会得到一个大规模如果您的队列包含很多元素,则在运行时增加

hth

0

我会做一个子类:

class MyDeduplicatedQueue : Queue<MyCustomObject> { 
    /// etc 
} 

然后你就可以把所有的适当的过滤逻辑到Enqueue方法。

0

我想使一个包装类,而不是从队列延伸,作为基本类型的队列用户期望不同的行为。 (当你这样做在.NET 4.0中的数据合同甚至可能会抱怨。)

内部,你可以有一个实际的队列到重定向所需要的呼叫。 每个Queue()调用你可以添加新元素到一个字典,当它不包含已经。在此之前,您可以清空该字典中超过x秒的所有元素,并按顺序将它们添加到内部队列中。

出队时,您必须检查内部队列中是否包含元素,否则挑从字典中最早的元素。

这只是一个可能的实现。当很多不同的元素可能会很快排队时,字典会很快填满,并且可能需要添加额外的逻辑来解决这个问题。

+0

public void QueueInput(HotSynchUnit.RcdFSWFile rcd) //在程序启动时启动工作线程。在程序退出例程或接近处理程序等 //调用Terminate.Set() { //锁定共享队列 锁(SharedQueue) { SharedQueue.Enqueue(RCD); SomethingToDo.Set(); } } // public void QueueInput – user610064 2011-02-09 17:43:39

0

为什么不只是拒绝插入,如果他们有重复的路径?您只需要从队列的尾部开始进行线性搜索,当您找到重复(并拒绝插入)或时间戳超出您的时间限制(并插入记录)时停止搜索?看起来比保持另一个数据结构和所有相关逻辑简单得多。