Waiting for the silence of events

I need to create a method to listen for events and wait for some silence before calling another function.

In particular, I am listening to a directory for updating files. When a file change occurs, my directoryUpdate function is called. From there, I add the file to the list and create a thread called "timerThread" that sleeps for 2 seconds. When this thread is sleeping, it calls the "gatherFinished" function.

But since directoryUpdate is called 10 times all at once, if 10 files change, it starts 10 threads, which seem like a bad way to do this.

At the end, I want a list of file changes that occurred within 2 seconds of each other. I believe that if there is a time to reset sleep mode to 2 seconds each time a change occurs and wait for 2 seconds to finish, then I will have what I need. But as far as I know, the reset timer does not exist.

What is the best way to do this?

UPDATE Thank you for all your wonderful answers. I apologize for focusing on getting a list of files. The event (file change) should not matter. I wanted to focus on making the โ€œgatherFinishedโ€ call happen once at the right time - 2 seconds after all the events in question stopped shooting. My question is about the nature of the wait, not the nature of the files or collections.

+4
source share
4 answers

You can just use AutoResetEvent and wait 2 seconds. If the event fires, you loop and wait another 2 seconds.

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(); } 

NOTE. I did not specify code to tell you how to synchronize a stream that will receive directory changes and a timer stream. You will have to do it yourself.

+3
source

One way to do this is to add each updated file to the list along with the timestamp when they will be added. Then, when your 2 second timer fires, you can check all the items in the list that have a timestamp that is older than the last time it started.

0
source

Hey Yona, This is a really really funny problem.

If I understand correctly, you are using FileSystemWatcher or some other similar object to monitor the folder.

Each time a file is added or modified, you get an event.

Now the problem is that this event can be raised at a relatively random time, and if you try to write all files that were changed within 2 seconds of each other, you will have many collections of objects.

What I would do is create a List<List<MyFileChangeClass>> , where MyFileChangeClass is any construct you use to track the changed information.

When you process the event to modify the file, create a new MyFileChangeClass with the necessary data and repeat the external list. For each list, make sure that the first MyFileChangeClass has a timestamp of less than 2 seconds before the current file modification; if so, add the file modification to the internal list.

Once you have finished the whole list, add a new List<MyFileChangeClass> to the external list, which is filled only with the current MyFileChangeClass . This ensures that future changes can be associated with the latter, and that you have all groups of modifications that occurred within 2 seconds of each other.

All around, I would enable the lock - perhaps ReaderWriterLockSlim using TryEnterWriteLock() .

I hope this helps - if you need more information, please let me know, but obviously you know a little about what you are doing, and maybe you just needed a little logical help, because this is a strange problem.

Good luck

Adam

0
source

I am going to assume that you are using the FileSystemWatcher class to monitor file system changes. Your problem is well suited to the consumer-manufacturer pattern. In your case, the manufacturer is FileSystemWatcher , which will add the modified files to the queue. Then the consumer will delete the file names from the queue as soon as they appear. The best part about this template is that only one workflow is involved, and all file changes will be processed in the order in which they are received.

Here is some code for you to get started.

 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. } } } 

From the FileSystemWatcher event handlers, you call QueueChangedFile . Add the code that you think is necessary to handle changes to the file in the Consume method after calling Take . You can make logic complex as needed. If you need to keep track of the time at which the changes occurred (so that you can later determine which files were changed within 2 seconds of each other), instead of having a string in the queue, you could create a simple class that stores as file path and time of change, and save this shell class instead.

0
source

All Articles