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 <IWorkspaceProjectContext?> CreateProjectContextHandlingFaultAsync(ProjectContextInitData data, object?hostObject) { try { // Call into Roslyn to init language service for this project IWorkspaceProjectContext context = await _workspaceProjectContextFactory.Value.CreateProjectContextAsync( data.LanguageName, data.WorkspaceProjectContextId, data.ProjectFilePath, data.ProjectGuid, hostObject, data.BinOutputPath, data.AssemblyName, CancellationToken.None); context.StartBatch(); try { // Update additional properties within a batch to avoid thread pool starvation. // https://github.com/dotnet/project-system/issues/8027 context.LastDesignTimeBuildSucceeded = false; // By default, turn off diagnostics until the first design time build succeeds for this project. // Pass along any early approximation we have of the command line options #pragma warning disable CS0618 // This was obsoleted in favor of the one that takes an array, but here just the string is easier; we'll un-Obsolete this API context.SetOptions(data.CommandLineArgsForDesignTimeEvaluation); #pragma warning restore CS0618 // Type or member is obsolete } finally { await context.EndBatchAsync(); } return(context); } catch (Exception ex) { await _faultHandlerService.ReportFaultAsync(ex, _project, ProjectFaultSeverity.LimitedFunctionality); } return(null); }
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); } }