private async Task ApplyProjectChangesUnderLockAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> update, bool evaluation, CancellationToken cancellationToken) { IWorkspaceProjectContext context = _contextAccessor !.Context; context.StartBatch(); try { bool isActiveContext = _activeWorkspaceProjectContextTracker.IsActiveEditorContext(_contextAccessor.ContextId); if (evaluation) { await _applyChangesToWorkspaceContext !.Value.ApplyProjectEvaluationAsync(update, isActiveContext, cancellationToken); } else { await _applyChangesToWorkspaceContext !.Value.ApplyProjectBuildAsync(update, isActiveContext, cancellationToken); } } finally { context.EndBatch(); NotifyOutputDataCalculated(update.DataSourceVersions, evaluation); } await _applyChangesToWorkspaceContext.Value.ApplyProjectEndBatchAsync(update, cancellationToken); }
internal Task OnProjectChangedAsync <T>( IDataProgressTrackerServiceRegistration registration, ConfiguredProject activeConfiguredProject, IProjectVersionedValue <T> update, Func <IProjectVersionedValue <T>, bool> hasChange, Action <IProjectVersionedValue <T>, IApplyChangesToWorkspaceContext, ContextState, CancellationToken> applyFunc) { return(ExecuteUnderLockAsync(ApplyProjectChangesUnderLockAsync, _tasksService.UnloadCancellationToken)); Task ApplyProjectChangesUnderLockAsync(CancellationToken cancellationToken) { // NOTE we cannot call CheckForInitialized here, as this method may be invoked during initialization Assumes.NotNull(_contextAccessor); Assumes.NotNull(_applyChangesToWorkspaceContext); if (!hasChange(update)) { // No change since the last update. We must still update operation progress, but can skip creating a batch. UpdateProgressRegistration(); return(Task.CompletedTask); } return(ApplyInBatchAsync()); async Task ApplyInBatchAsync() { ContextState contextState = new( isActiveEditorContext : _activeWorkspaceProjectContextTracker.IsActiveEditorContext(_contextAccessor.ContextId), isActiveConfiguration : activeConfiguredProject == _project); IWorkspaceProjectContext context = _contextAccessor.Context; context.StartBatch(); try { applyFunc(update, _applyChangesToWorkspaceContext.Value, contextState, cancellationToken); } finally { await context.EndBatchAsync(); UpdateProgressRegistration(); } } void UpdateProgressRegistration() { // Notify operation progress that we've now processed these versions of our input, if they are // up-to-date with the latest version that produced, then we no longer considered "in progress". registration.NotifyOutputDataCalculated(update.DataSourceVersions); } } }
private async Task ApplyProjectChangesUnderLockAsync(ProjectChange change, WorkspaceContextHandlerType handlerType, CancellationToken cancellationToken) { // NOTE we cannot call CheckForInitialized here, as this method may be invoked during initialization Assumes.NotNull(_contextAccessor); IWorkspaceProjectContext context = _contextAccessor.Context; bool isActiveEditorContext = _activeWorkspaceProjectContextTracker.IsActiveEditorContext(_contextAccessor.ContextId); bool isActiveConfiguration = change.Project == _project; var state = new ContextState(isActiveEditorContext, isActiveConfiguration); context.StartBatch(); try { switch (handlerType) { case WorkspaceContextHandlerType.Evaluation: await _applyChangesToWorkspaceContext !.Value.ApplyProjectEvaluationAsync(change.Subscription, state, cancellationToken); break; case WorkspaceContextHandlerType.ProjectBuild: Assumes.NotNull(change.BuildSnapshot); await _applyChangesToWorkspaceContext !.Value.ApplyProjectBuildAsync(change.Subscription, change.BuildSnapshot, state, cancellationToken); break; case WorkspaceContextHandlerType.SourceItems: await _applyChangesToWorkspaceContext !.Value.ApplySourceItemsAsync(change.Subscription, state, cancellationToken); break; } } finally { await context.EndBatchAsync(); NotifyOutputDataCalculated(change.DataSourceVersions, handlerType); } }