protected virtual void OnResultsReady(DocumentStructureChangedEventArgs args)
 {
     using (SynchronizeMainThreadState())
     {
         ResultsReady?.Invoke(this, args);
     }
 }
        private void OnResultsReady(object sender, DocumentStructureChangedEventArgs args)
        {
            _dispatcher.AssertBackgroundThread();

            if (DocumentStructureChanged != null)
            {
                if (args.Snapshot != _textBuffer.CurrentSnapshot)
                {
                    // A different text change is being parsed.
                    return;
                }

                CodeDocument   = args.CodeDocument;
                Snapshot       = args.Snapshot;
                _partialParser = new RazorSyntaxTreePartialParser(CodeDocument.GetSyntaxTree());
                DocumentStructureChanged(this, args);
            }
        }
            public void ReturnParcel(DocumentStructureChangedEventArgs args)
            {
                lock (_stateLock)
                {
                    // Clear the current parcel cancellation source
                    if (_currentParcelCancelSource != null)
                    {
                        _currentParcelCancelSource.Dispose();
                        _currentParcelCancelSource = null;
                    }

                    // If there are things waiting to be parsed, just don't fire the event because we're already out of date
                    if (_changes.Any())
                    {
                        return;
                    }
                }
                var handler = ResultsReady;

                if (handler != null)
                {
                    handler(this, args);
                }
            }
            // **** BACKGROUND THREAD ****
            private void WorkerLoop()
            {
                var fileNameOnly = Path.GetFileName(_filePath);

                try
                {
                    EnsureOnThread();

                    while (!_shutdownToken.IsCancellationRequested)
                    {
                        // Grab the parcel of work to do
                        var parcel = _main.GetParcel();
                        if (parcel.Edits.Any())
                        {
                            try
                            {
                                DocumentStructureChangedEventArgs args = null;
                                using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken))
                                {
                                    if (!linkedCancel.IsCancellationRequested)
                                    {
                                        // Collect ALL changes
                                        List <Edit> allEdits;

                                        if (_previouslyDiscarded != null)
                                        {
                                            allEdits = Enumerable.Concat(_previouslyDiscarded, parcel.Edits).ToList();
                                        }
                                        else
                                        {
                                            allEdits = parcel.Edits.ToList();
                                        }

                                        var finalEdit = allEdits.Last();

                                        var results = ParseChange(finalEdit.Snapshot, linkedCancel.Token);

                                        if (results != null && !linkedCancel.IsCancellationRequested)
                                        {
                                            // Clear discarded changes list
                                            _previouslyDiscarded = null;

                                            _currentSyntaxTree = results.GetSyntaxTree();

                                            // Build Arguments
                                            args = new DocumentStructureChangedEventArgs(
                                                finalEdit.Change,
                                                finalEdit.Snapshot,
                                                results);
                                        }
                                        else
                                        {
                                            // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set
                                            _previouslyDiscarded = allEdits;
                                        }
                                    }
                                }
                                if (args != null)
                                {
                                    _main.ReturnParcel(args);
                                }
                            }
                            catch (OperationCanceledException)
                            {
                            }
                        }
                        else
                        {
                            Thread.Yield();
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    // Do nothing. Just shut down.
                }
                finally
                {
                    // Clean up main thread resources
                    _main.Dispose();
                }
            }