等待事件静默

本文关键字:静默 事件 等待 | 更新日期: 2023-09-27 17:55:46

我需要创建一个方法来侦听事件并在调用另一个函数之前等待一定程度的静音。

具体来说,我正在收听文件更新目录。当文件发生更改时,我的"目录更新"函数被调用。从那里,我将文件添加到列表中,并创建一个名为"timerThread"的线程,该线程休眠2秒钟。当该线程完成休眠后,它会调用"gatherDone"函数。

但是由于如果 10 个文件更改,directoryUpdate 会一次调用 10 次,因此它将启动 10 个线程,这似乎是一种糟糕的方法。

最后,我想要一个在 2 秒内发生的文件更改的列表。我想如果有办法在每次发生变化时将睡眠时间重置为 2 秒并等待 2 秒完成,那么我将拥有我需要的东西。但是据我所知,没有办法重置计时器。

最好的方法是什么?

更新感谢您所有精彩的回答。很抱歉强调获取文件列表。事件(文件更改)应该无关紧要。我的意思是专注于确保对"gatherDone"的调用在正确的时间发生一次 - 在所有有问题的事件停止触发后 2 秒。我的问题是关于等待的性质,而不是文件或集合的性质。

等待事件静默

您可以使用自动重置事件并等待 2 秒钟。如果事件被触发,则循环并再等待 2 秒。

        AutoResetEvent resetTimer = new AutoResetEvent(false);
        ...
        private void TimerJob()
        {
            ...
            // The thread will sleep and loop until 
            // 2 seconds elapse without directory changes 
            while (resetTimer.WaitOne(2000)) {}
            ...
        }
        private void ResetTimer()
        {
            resetTimer.Set();
        }

注意:我没有放置任何代码来指定如何同步将接收目录更改的线程和计时器线程。你必须自己做。

一种方法是将每个更新的文件添加到列表中,以及添加它们的时间戳。然后,当 2 秒计时器触发时,您可以检查列表中时间戳早于上次触发时间的任何项目。

嘿乔诺,这实际上是一个非常有趣的问题。

如果我理解正确,您正在使用文件系统观察器或其他类似对象来监视文件夹。

每次添加或更改文件时,您都会收到一个事件。

现在的问题是这个事件可以在相对随机的时间引发,如果你试图记录所有在 2 秒内被修改的文件,你将拥有许多对象集合。

我要做的是创建一个List<List<MyFileChangeClass>>,其中MyFileChangeClass是你用来跟踪更改的信息的任何结构。

处理文件修改事件时,请使用必要的详细信息创建新MyFileChangeClass并循环访问外部列表。 对于每个列表,请检查第一个MyFileChangeClass在当前文件修改之前的时间戳是否小于 2 秒,如果是,请将文件修改添加到内部列表。

浏览完整个列表后,将新List<MyFileChangeClass>添加到外部列表,该列表仅填充当前MyFileChangeClass。 这将确保将来的修改可以与最新的修改相关联,并且您拥有在 2 秒内发生的所有修改分组。

在整个事情周围,我会包括一个锁 - 可能是使用 TryEnterWriteLock()ReaderWriterLockSlim

我希望这有所帮助 - 如果您需要更多详细信息,请告诉我,但显然您对自己正在做的事情有所了解,可能只需要一些逻辑帮助,因为这是一个奇怪的问题。

祝你好运!

亚当

我将假设您正在使用FileSystemWatcher类来监视文件系统更改。您的问题非常适合生产者-消费者模式。在您的情况下,生产者是将更改的文件添加到队列FileSystemWatcher。然后,使用者将在文件名出现后将其从队列中取消排队。这种模式的好处是只涉及一个工作线程,所有文件更改都将按照接收顺序进行处理。

下面是一些帮助您入门的代码。

public class Example
{
  private BlockingCollection<string> m_Queue = new BlockingCollection<string>();
  public Example()
  {
    var thread = new Thread(Consumer);
    thread.IsBackground = true;
    thread.Start();
  }
  public void QueueChangedFile(string filePath)
  {
    m_Queue.Add(filePath);
  }
  private void Consumer()
  {
    while (true)
    {
      // The Take method blocks until an item appears in the queue.
      string filePath = m_Queue.Take();
      // Do whatever you need to do with the file here.
    }
  }
}

FileSystemWatcher事件处理程序中,您将调用 QueueChangedFile 。在调用 Take 之后,添加您认为在 Consume 方法中处理文件更改所需的任何代码。您可以根据需要使逻辑尽可能复杂。如果您需要跟踪更改发生的时间(以便以后可以确定哪些文件在 2 秒内相互更改),那么与其让队列保存string,不如创建一个简单的类来存储文件路径和更改时间,并让队列存储该包装类。