views:

56

answers:

3

Out of curiosity, is it possible to implement an interval at which the various events are raised when using the FileSystemWatcher?

Thanks!

A: 

Short answer - no. The class is event based. It does not have polling capabilities.

Ryan Bennett
+2  A: 

There's an overload of FileSystemWatcher.WaitForChanged that take a timeout:

A synchronous method that returns a structure that contains specific information on the change that occurred, given the type of change you want to monitor and the time (in milliseconds) to wait before timing out.

So if your event doesn't happen before the timeout period you've set expires the event won't get fired.

I don't think there's a method/property that sets the minimum time between events.

ChrisF
A: 

Short answer...maybe.

It depends on how this interval would be interpreted. If you want the FileSystemWatcher to raise one of its events periodically regardless of whether or not something actually changed then the answer is no.

But, if this interval is meant to control the minimum amount of time that has to elaspe prior to raising the next event then the asnwer is most definitely yes! The trick is to intercept the raising of the events and throttle them using a middle-man. Now this is only possible on a FileSystemWatcher (and a relatively small set of other event based classes) due to the fact that you can assign an ISynchronizeInvoke instance to the SynchronizingObject property. The synchronizing object would act as the middle-man and enforce the interval constraint.

Disclaimer: I am in no way advocating that anyone actually try this for various different reasons.

public void Main()
{
  var watcher = new FileSystemWatcher();
  watcher.SynchronizingObject = new Synchronizer(TimeSpan.FromSeconds(30));
}

public class Synchronizer : ISynchronizeInvoke 
{ 
    private TimeSpan m_Interval;
    private Thread m_Thread; 
    private BlockingCollection<Message> m_Queue = new BlockingCollection<Message>(); 

    public Synchronizer(TimeSpan interval) 
    { 
        m_Interval = interval;
        m_Thread = new Thread(Run); 
        m_Thread.IsBackground = true; 
        m_Thread.Start(); 
    } 

    private void Run() 
    { 
        DateTime last = DateTime.MinValue;
        while (true) 
        { 
            Message message = m_Queue.Take();
            DateTime received = DateTime.UtcNow;
            TimeSpan span = DateTime.UtcNow - last;
            TimeSpan wait = m_Interval - span;
            if (wait > TimeSpan.Zero)
            {
              Thread.Sleep(wait);
            }
            message.Return = message.Method.DynamicInvoke(message.Args); 
            message.Finished.Set(); 
            last = received;
        } 
    } 

    public IAsyncResult BeginInvoke(Delegate method, object[] args) 
    { 
        Message message = new Message(); 
        message.Method = method; 
        message.Args = args; 
        m_Queue.Add(message); 
        return message; 
    } 

    public object EndInvoke(IAsyncResult result) 
    { 
        Message message = result as Message; 
        if (message != null) 
        { 
            message.Finished.WaitOne(); 
            return message.Return; 
        } 
        throw new ArgumentException("result"); 
    } 

    public object Invoke(Delegate method, object[] args) 
    { 
        Message message = new Message(); 
        message.Method = method; 
        message.Args = args; 
        m_Queue.Add(message); 
        message.Finished.WaitOne(); 
        return message.Return; 
    } 

    public bool InvokeRequired 
    { 
        get { return Thread.CurrentThread != m_Thread; } 
    } 

    private class Message : IAsyncResult 
    { 
        public Delegate Method = null; 
        public object[] Args = null; 
        public object Return = null; 
        public object State = null; 
        public ManualResetEvent Finished = new ManualResetEvent(false); 

        public object AsyncState 
        { 
            get { return State; } 
        } 

        public WaitHandle AsyncWaitHandle 
        { 
            get { return Finished; } 
        } 

        public bool CompletedSynchronously 
        { 
            get { return false; } 
        } 

        public bool IsCompleted 
        { 
            get { return Finished.WaitOne(0); } 
        } 
    } 
} 
Brian Gideon