internal async Task OnProjectChangedAsync_WhenProjectUnloaded_TriggersCancellation(WorkspaceContextHandlerType handlerType)
        {
            var unloadSource = new CancellationTokenSource();
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(unloadSource.Token);

            void ApplyProjectBuild(IProjectVersionedValue <IProjectSubscriptionUpdate> _, IProjectBuildSnapshot projectBuildSnapshot, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            void ApplyProjectEvaluation(IProjectVersionedValue <IProjectSubscriptionUpdate> _, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            var applyChangesToWorkspaceContext = handlerType switch
            {
                WorkspaceContextHandlerType.Evaluation => IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectEvaluationAsync(ApplyProjectEvaluation),
                WorkspaceContextHandlerType.ProjectBuild => IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectBuildAsync(ApplyProjectBuild),
                WorkspaceContextHandlerType.SourceItems => IApplyChangesToWorkspaceContextFactory.ImplementApplySourceItemsAsync(ApplyProjectEvaluation), // ApplyProjectEvaluation works for source items as they share a signature
                _ => throw new NotImplementedException()
            };

            var instance = await CreateInitializedInstanceAsync(tasksService : tasksService, applyChangesToWorkspaceContext : applyChangesToWorkspaceContext);

            var update = IProjectVersionedValueFactory.Create <(ConfiguredProject, IProjectSubscriptionUpdate, IProjectBuildSnapshot)>((default !, default !, Mock.Of <IProjectBuildSnapshot>()));
            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);
                }
            }
            private void NotifyOutputDataCalculated(IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions, WorkspaceContextHandlerType handlerType)
            {
                // 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".
                switch (handlerType)
                {
                case WorkspaceContextHandlerType.Evaluation:
                    _evaluationProgressRegistration !.NotifyOutputDataCalculated(dataSourceVersions);
                    break;

                case WorkspaceContextHandlerType.ProjectBuild:
                    _projectBuildProgressRegistration !.NotifyOutputDataCalculated(dataSourceVersions);
                    break;

                case WorkspaceContextHandlerType.SourceItems:
                    _sourceItemsProgressRegistration !.NotifyOutputDataCalculated(dataSourceVersions);
                    break;
                }
            }
 internal Task OnProjectChangedAsync(ProjectChange change, WorkspaceContextHandlerType handlerType)
 {
     return(ExecuteUnderLockAsync(ct => ApplyProjectChangesUnderLockAsync(change, handlerType, ct), _tasksService.UnloadCancellationToken));
 }