等待事件沉默

时间:2011-05-10 17:30:42

标签: c# multithreading timer

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

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

但是,如果10个文件发生变化,则一次性调用directoryUpdate 10次,那么它将启动10个线程,这似乎是一种不好的方式。

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

这样做的最佳方式是什么?

更新 谢谢你所有的好答案。我很抱歉强调获取文件列表。事件(文件更改)无关紧要。我的目的是集中精力确保在所有相关事件停止射击后2秒钟,在正确的时间调用“gatherFinished”。我的问题是等待的性质,而不是文件或集合的性质。

4 个答案:

答案 0 :(得分:3)

您可以使用AutoResetEvent并等待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();
        }

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

如果我理解正确,您正在使用FileSystemWatcher或其他类似对象来监控文件夹。

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

现在的问题是这个事件可以在相对随机的时间引发,如果你想要记录所有在彼此之后2秒内被修改过的文件,你将拥有许多对象集合。 / p>

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

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

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

围绕整个事情,我会包含一个锁定 - 可能是ReaderWriterLockSlim使用TryEnterWriteLock()

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

祝你好运!

亚当

答案 3 :(得分:0)

我将假设您正在使用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。在调用Consume之后,添加您认为在Take方法中处理文件更改所需的任何代码。您可以根据需要使逻辑变得复杂。如果您需要跟踪更改发生的时间(以便稍后可以确定哪些文件在彼此的2秒内更改),那么您可以创建一个简单的类,而不是让队列保持string。它存储文件路径和更改时间,并让队列存储该包装类。