Microsoft.R.Editor.Tree.TreeUpdateTask.ApplyBackgroundProcessingResults C# (CSharp) Method

ApplyBackgroundProcessingResults() private method

Applies queued changes to the tree. Must only be called in a main thread context.
private ApplyBackgroundProcessingResults ( ) : void
return void
        internal void ApplyBackgroundProcessingResults() {
            if (_ownerThreadId != Thread.CurrentThread.ManagedThreadId)
                throw new ThreadStateException("Method should only be called on the main thread");

            if (_disposed)
                return;

            EditorTreeChangeCollection treeChanges;
            var eventsToFire = new List<TreeChangeEventRecord>();
            bool changed = false;
            bool fullParse = false;
            bool staleChanges = false;

            while (_backgroundParsingResults.TryDequeue(out treeChanges)) {
                // If no changes are pending, then main thread already processes
                // everything in EnsureProcessingComplete call. Changes are pending
                // until they are applied to the tree. If queue is not empty
                // it either contains stale changes or main thread had to handle
                // changes in sync per request from, say, intellisense or formatting.
                if (ChangesPending) {
                    // Check if background processing result matches current text buffer snapshot version
                    staleChanges = (TextBuffer != null && treeChanges.SnapshotVersion < TextBuffer.CurrentSnapshot.Version.VersionNumber);

                    if (!staleChanges) {
                        // We can't fire events when appying changes since listeners may
                        // attempt to access tree which is not fully updated and/or may
                        // try to acquire read lock and hang since ApplyTreeChanges
                        // hols write lock.

                        eventsToFire = ApplyTreeChanges(treeChanges);
                        fullParse = _pendingChanges.FullParseRequired;

                        // Queue must be empty by now since only most recent changes are not stale
                        // Added local variable as I hit this assert, but _backgroundParsingResults.Count was zero
                        //   by the time I broke into the debugger. If this hits again, we may need to 
                        //   think through this code and whether we need to be protecting against concurrent access.
                        int count = _backgroundParsingResults.Count;
                        Debug.Assert(count == 0);

                        // Clear pending changes as we are done
                        ClearChanges();

                        changed = true;

                        // No need for further processing as queue must be empty
                        break;
                    }
                }
            }

            if (!staleChanges) {
                // Now that tree is fully updated, fire events
                if (_editorTree != null) {
                    if (changed) {
                        _editorTree.FirePostUpdateEvents(eventsToFire, fullParse);
                        DebugTree.VerifyTree(_editorTree);
                    }

                    if (!ChangesPending) {
                        Debug.Assert(_editorTree.AstRoot.Children.Count > 0);
                    }
                }
            }
        }