private void ProcessChangedPathEvents() { Invariants.Assert(StateHost.PollingThread.IsThread(Thread.CurrentThread)); var morePathsChanged = DequeueChangedPathsEvents(); // If we got more changes, reset the polling interval for the non-simple // path changed. The goal is to avoid processing those too frequently if // there is activity on disk (e.g. a build happening), because // processing add/delete changes is currently much more expensive in the // search engine file database. // Note we don't update the simple "file change" events, as those as cheaper // to process. if (morePathsChanged.Count > 0) { _simplePathChangesPolling.Checkpoint(); _pathChangesPolling.Checkpoint(); } // Merge the new events into the existing events morePathsChanged.ForAll(change => MergePathChange(_bufferedChangedPaths, change.Value)); // Post changes that belong to an expired polling interval. if (_simplePathChangesPolling.WaitTimeExpired()) { PostPathsChangedEvents(_bufferedChangedPaths, x => x == PathChangeKind.Changed); _simplePathChangesPolling.Restart(); } if (_pathChangesPolling.WaitTimeExpired()) { PostPathsChangedEvents(_bufferedChangedPaths, x => true); _pathChangesPolling.Restart(); } if (_bufferedChangedPaths.Count == 0) { // We are done processing all changes, make sure we wait at least some // amount of time before processing anything more. _simplePathChangesPolling.Restart(); _pathChangesPolling.Restart(); } }
/// <summary> /// The OS FileSystem notification does not notify us if a directory used for /// change notification is deleted (or renamed). We have to use polling to detect /// this kind of changes. /// </summary> private void CheckDeletedRoots() { Invariants.Assert(StateHost.PollingThread.IsThread(Thread.CurrentThread)); if (!_checkRootsPolling.WaitTimeExpired()) { return; } _checkRootsPolling.Restart(); var deletedWatchers = StateHost.WatcherDictionary .Where(item => !StateHost.ParentWatcher._fileSystem.DirectoryExists(item.Key)) .ToList(); deletedWatchers .ForAll(item => { EnqueueChangeEvent(item.Key, RelativePath.Empty, PathChangeKind.Deleted, PathKind.Directory); RemoveDirectory(item.Key); }); }