C# 如何在一个时间范围内从队列中删除重复项?

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

我想以一种有效的方式从队列中删除重复的条目。 队列有一个自定义类,其中包含DateTime和FullPath以及其他一些内容

private Queue<MyCustomClass> SharedQueue;
专用队列SharedQueue;
类中的DateTime是插入队列时的时间戳。我想使用的逻辑如下:如果完整路径在4秒钟的窗口内相同(即,如果在复制完整路径的4秒钟内添加到队列中),则从队列中删除重复项。我有我想看的赛事,但仍会有几场复赛,这没关系

我正在使用c#2.0、FileSystemWatcher类和工作队列

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

或者我应该使用“全局私有”变量字典?这样我就可以快速搜索它了?还是队列的本地副本?如果发生许多文件事件,最好将本地队列限制为100个项目?虽然在我的例子中,它“应该”只是一个文件夹中要监视的相对较少的文件。。。但事情总是在变

谢谢你的帮助

:编辑:2月10日8:54美国东部时间: 所以我决定实施一个很好的简单的解决方案。 我想我没有把听写键握得太久

:Edit:Feb 10 9:53 EST:已更新,因为我的字典不能包含重复的值

   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——当然您是对的——在最初的问题中