protected void RaiseEvents(Queue deQueue)
        {
            if ((deQueue != null) && (deQueue.Count > 0))
            {
                DelayedEvent de = null;
                while (deQueue.Count > 0)
                {
                    de = deQueue.Dequeue() as DelayedEvent;
                    switch (de.Args.ChangeType)
                    {
                    case WatcherChangeTypes.Changed:
                        this.OnChanged(de.Args);
                        break;

                    case WatcherChangeTypes.Created:
                        this.OnCreated(de.Args);
                        break;

                    case WatcherChangeTypes.Deleted:
                        this.OnDeleted(de.Args);
                        break;

                    case WatcherChangeTypes.Renamed:
                        this.OnRenamed(de.Args as RenamedEventArgs);
                        break;
                    }
                }
            }
        }
        private void ElapsedEventHandler(Object sender, ElapsedEventArgs e)
        {
            // We don't fire the events inside the lock. We will queue them here until
            // the code exits the locks.
            Queue eventsToBeFired = null;

            if (System.Threading.Monitor.TryEnter(this._enterThread))
            {
                // Only one thread at a time is processing the events
                try
                {
                    eventsToBeFired = new Queue(32);
                    // Lock the collection while processing the events
                    lock (this._events.SyncRoot)
                    {
                        DelayedEvent current = null;
                        for (int i = 0; i < this._events.Count; i++)
                        {
                            current = this._events[i] as DelayedEvent;
                            if (current.Delayed)
                            {
                                // This event has been delayed already so we can fire it
                                // We just need to remove any duplicates
                                for (int j = i + 1; j < this._events.Count; j++)
                                {
                                    if (current.IsDuplicate(this._events[j]))
                                    {
                                        // Removing later duplicates
                                        this._events.RemoveAt(j);
                                        j--; // Don't skip next event
                                    }
                                }
                                // Add the event to the list of events to be fired
                                eventsToBeFired.Enqueue(current);
                                // Remove it from the current list
                                this._events.RemoveAt(i);
                                i--; // Don't skip next event
                            }
                            else
                            {
                                // This event was not delayed yet, so we will delay processing
                                // this event for at least one timer interval
                                current.Delayed = true;
                            }
                        }
                    }
                }
                finally
                {
                    System.Threading.Monitor.Exit(this._enterThread);
                }
            }
            // else - this timer event was skipped, processing will happen during the next timer event

            // Now fire all the events if any events are in eventsToBeFired
            this.RaiseEvents(eventsToBeFired);
        }