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