是否可以在FileSystemWatcher上设置间隔?

时间:2010-08-30 18:30:50

标签: c# .net-3.5 file-io

出于好奇,是否可以在使用FileSystemWatcher时实现引发各种事件的时间间隔?

谢谢!

3 个答案:

答案 0 :(得分:4)

FileSystemWatcher.WaitForChanged超载导致超时:

  

一种同步方法,它返回一个结构,该结构包含有关发生的更改的特定信息,给定要监视的更改类型以及超时前等待的时间(以毫秒为单位)。

因此,如果您的事件未在您设置的超时期限之前发生,则事件不会被触发。

我认为没有一个方法/属性可以设置事件之间的最短时间。

答案 1 :(得分:0)

简短回答 - 不。该课程以事件为基础。它没有轮询功能。

答案 2 :(得分:0)

简短回答......也许。

这取决于如何解释这个间隔。如果您希望FileSystemWatcher定期提升其中一个事件,而不管某些事件是否实际发生了变化,那么答案就是否定。

但是,如果这个间隔是为了控制在提升下一个事件之前必须进行elaspe的最短时间,那么asnwer肯定是肯定的!诀窍是拦截事件的发生并用中间人扼杀他们。现在这只能在FileSystemWatcher(和一组相对较小的其他基于事件的类)上实现,因为您可以将ISynchronizeInvoke实例分配给SynchronizingObject属性。同步对象将充当中间人并强制执行间隔约束。

免责声明:我绝不主张任何人出于各种不同的原因尝试这一点。

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