C# 如何在一个时间范围内从队列中删除重复项?
我想以一种有效的方式从队列中删除重复的条目。 队列有一个自定义类,其中包含DateTime和FullPath以及其他一些内容C# 如何在一个时间范围内从队列中删除重复项?,c#,queue,filesystemwatcher,no-duplicates,C#,Queue,Filesystemwatcher,No Duplicates,我想以一种有效的方式从队列中删除重复的条目。 队列有一个自定义类,其中包含DateTime和FullPath以及其他一些内容 private Queue<MyCustomClass> SharedQueue; 专用队列SharedQueue; 类中的DateTime是插入队列时的时间戳。我想使用的逻辑如下:如果完整路径在4秒钟的窗口内相同(即,如果在复制完整路径的4秒钟内添加到队列中),则从队列中删除重复项。我有我想看的赛事,但仍会有几场复赛,这没关系 我正在使用c#2.0、Fi
private Queue<MyCustomClass> SharedQueue;
专用队列SharedQueue;
类中的DateTime是插入队列时的时间戳。我想使用的逻辑如下:如果完整路径在4秒钟的窗口内相同(即,如果在复制完整路径的4秒钟内添加到队列中),则从队列中删除重复项。我有我想看的赛事,但仍会有几场复赛,这没关系
我正在使用c#2.0、FileSystemWatcher类和工作队列
有很多方法可以做到这一点:
每次向队列中添加项目时,或在处理队列时修剪队列,跳过当前重复项目的处理
或者我应该使用“全局私有”变量字典 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
}
public void QueueInput(HotSynchUnit.RcdFSWFile rcd)
//当程序启动时启动辅助线程。
//在程序退出例程或关闭处理程序等中调用Terminate.Set()。
{
//锁定共享队列
锁(共享队列)
{
如果(!IsDuplicateQueueInput(rcd))//只向队列添加唯一值
{
SharedQueue.Enqueue(rcd);
SomethingToDo.Set();
}
}
}//公共无效队列输入
私有bool IsDuplicateQueueInput(HotSynchUnit.RcdFSWFile rcd)
/*如果对象是重复对象,则返回true。
*伪代码:
*
*isDuplicate=false
*锁字典
*-如果lastTimeStamp>4秒前,则//优化:保存lastTimeStamp
*如果字典计数>0,则清除字典
*返回是重复的
*-如果不是Dict.TryGetValue(sPath、dtTimeStamp),则
*编辑:AddKey()
*-其他
*将键时间戳与Currenttime进行比较
*如果key timestamp是我将创建一个子类:
class MyDeduplicatedQueue : Queue<MyCustomObject> {
/// etc
}
类MyDeduplicatedQueue:队列{
///等
}
然后,您可以将所有适当的过滤逻辑放入Enqueue
方法。我将创建一个包装类,而不是从队列扩展,因为基类型队列的用户期望不同的行为。(当您这样做时,.NET 4.0中的数据契约甚至可能会抱怨。)
在内部,您可以有一个实际的队列来重定向所需的调用。
每次Queue()调用都可以在新元素尚未包含时将其添加到字典中。在执行此操作之前,可以从该字典中清空所有早于x秒的元素,并按顺序将它们添加到内部队列中
退出队列时,必须检查内部队列是否包含元素,否则从字典中选择最早的元素
当然,这只是一种可能的实现。当许多不同的元素可能很快排队时,字典会很快填满,可能需要添加额外的逻辑来解决这个问题。我刚刚考虑过使用任何类似于通用哈希表的集合。。。大概是这样的:
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如果插入具有重复路径,为什么不直接拒绝它们?您所要做的就是从队列尾部开始线性搜索,并在找到重复项(并拒绝插入)或时间戳超过时间限制(并插入记录)时停止搜索?似乎比保留另一个数据结构和所有相关逻辑简单得多。为什么使用“全局专用”词典?为什么不把它放在与队列相同的范围内呢?事实上,它就在这个范围内。我的错。谢谢@StevenJeuris在我排队前检查的想法-我忘了我在那里有那个例行程序。我不想覆盖或扩展类…public void QueueInput(HotSynchUnit.RcdFSWFile rcd)//在程序启动时启动工作线程。//在程序退出例程或关闭处理程序等中调用Terminate.Set()。{//lock shared queue lock(SharedQueue){SharedQueue.Enqueue(rcd);SomethingToDo.Set();}}//public void QueueInputYes,似乎是这样。正如我所说,不同的实现是可能的。当使用本地队列而不是字典时,您可以用添加时的查找时间速度来换取清除超过x秒的添加元素的速度。您也可以同时使用这两种方法,在这两种情况下以内存使用率换取速度:我的建议是,先简单编写,当性能不够时,相应地更新解决方案。好的,谢谢。现在,在调用Enqueu之前,我将在QueueInput例程中使用字典。为了简单起见,我更喜欢使用字典,而不是同步队列。我将把字典计数限制在1000行左右?现在的处理器性能非常好;P1000元素不应该造成太多问题。您不需要检查密钥的存在。您只需删除该检查,并使dict.add成为dict[key]=“demo.txt”,您将得到相同的结果,但只是稍微干净一点。这是我基本上已经在使用字典,但锁定字典并将其限制为n行。我对CheckForInterval()以及您将如何实现这一点感兴趣。@philip——当然您是对的——在最初的问题中