private void ParseDocumentAsync(Document document) { var cancellationTokenSource = new CancellationTokenSource(); using (_stateLock.DisposableWrite()) { _workMap = _workMap.Add(document.Id, cancellationTokenSource); } var cancellationToken = cancellationTokenSource.Token; var task = _taskScheduler.ScheduleTask( () => document.GetSyntaxTreeAsync(cancellationToken), "BackgroundParser.ParseDocumentAsync", cancellationToken); // Always ensure that we mark this work as done from the workmap. task.SafeContinueWith( _ => { using (_stateLock.DisposableWrite()) { // Check that we are still the active parse in the workmap before we remove it. // Concievably if this continuation got delayed and another parse was put in, we might // end up removing the tracking for another in-flight task. if (_workMap.TryGetValue(document.Id, out var sourceInMap) && sourceInMap == cancellationTokenSource) { _workMap = _workMap.Remove(document.Id); } } }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default); }
private void ParseDocumentAsync(Document document) { var cancellationTokenSource = new CancellationTokenSource(); using (_stateLock.DisposableWrite()) { _workMap = _workMap.Add(document.Id, cancellationTokenSource); } var cancellationToken = cancellationTokenSource.Token; var task = _taskScheduler.ScheduleTask( () => document.GetSyntaxTreeAsync(cancellationToken), "BackgroundParser.ParseDocumentAsync", cancellationToken); // Always ensure that we mark this work as done from the workmap. task.SafeContinueWith( _ => { using (_stateLock.DisposableWrite()) { _workMap = _workMap.Remove(document.Id); } }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default); }
private void BuildCompilationsAsync( Solution solution, ProjectId initialProject, ISet <ProjectId> allProjects) { var cancellationToken = _cancellationSource.Token; _compilationScheduler.ScheduleTask( () => BuildCompilationsAsync(solution, initialProject, allProjects, cancellationToken), "BackgroundCompiler.BuildCompilationsAsync", cancellationToken); }
private void OnGlobalOptionServiceOptionChanged(object sender, OptionChangedEventArgs e) { _taskQueue?.ScheduleTask(() => { // Ensure we grab the event handlers inside the scheduled task to prevent a race of people unsubscribing // but getting the event later on the UI thread var eventHandlers = GetEventHandlers(); foreach (var handler in eventHandlers) { handler(this, e); } }, "OptionsService.SetOptions"); }
private void OnGlobalOptionServiceOptionChanged(object sender, OptionChangedEventArgs e) { var eventHandlers = GetEventHandlers(); if (eventHandlers.Length > 0) { _taskQueue?.ScheduleTask(() => { foreach (var handler in eventHandlers) { handler(this, e); } }, "OptionsService.SetOptions"); } }
private void ParseDocumentAsync(Document document) { var cancellationTokenSource = new CancellationTokenSource(); using (_stateLock.DisposableWrite()) { _workMap = _workMap.Add(document.Id, cancellationTokenSource); } var cancellationToken = cancellationTokenSource.Token; // We end up creating a chain of parsing tasks that each attempt to produce // the appropriate syntax tree for any given document. Once we start work to create // the syntax tree for a given document, we don't want to stop. // Otherwise we can end up in the unfortunate scenario where we keep cancelling work, // and then having the next task re-do the work we were just in the middle of. // By not cancelling, we can reuse the useful results of previous tasks when performing later steps in the chain. // // we still cancel whole task if the task didn't start yet. we just don't cancel if task is started but not finished yet. var task = _taskScheduler.ScheduleTask( () => document.GetSyntaxTreeAsync(CancellationToken.None), "BackgroundParser.ParseDocumentAsync", cancellationToken); // Always ensure that we mark this work as done from the workmap. task.SafeContinueWith( _ => { using (_stateLock.DisposableWrite()) { // Check that we are still the active parse in the workmap before we remove it. // Concievably if this continuation got delayed and another parse was put in, we might // end up removing the tracking for another in-flight task. if (_workMap.TryGetValue(document.Id, out var sourceInMap) && sourceInMap == cancellationTokenSource) { _workMap = _workMap.Remove(document.Id); } } }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default); }
/// <summary> /// Executes an action as a background task, as part of a sequential queue of tasks. /// </summary> protected internal Task ScheduleTask(Action action, string taskName = "Workspace.Task") { return(_taskQueue.ScheduleTask(action, taskName)); }