private Task ProjectPropertyChangedAsync(Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> sources) { IVsProjectRestoreInfo projectRestoreInfo = ProjectRestoreInfoBuilder.Build(sources.Item1, _projectVsServices.Project); if (projectRestoreInfo != null) { _projectVsServices.Project.Services.ProjectAsynchronousTasks .RegisterAsyncTask(JoinableFactory.RunAsync(async() => { LogProjectRestoreInfo(_projectVsServices.Project.FullPath, projectRestoreInfo); await _solutionRestoreService .NominateProjectAsync(_projectVsServices.Project.FullPath, projectRestoreInfo, _projectVsServices.Project.Services.ProjectAsynchronousTasks.UnloadCancellationToken) .ConfigureAwait(false); CodeMarkers.Instance.CodeMarker(CodeMarkerTimerId.PerfPackageRestoreEnd); CompleteLogProjectRestoreInfo(_projectVsServices.Project.FullPath); }), ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); } return(Task.CompletedTask); }
/// <summary> /// Entry point for progression. Gets called every time when progression /// - Needs to know if a node has children /// - Wants to get children for a node /// - During solution explorer search /// </summary> public void BeginGetGraphData(IGraphContext context) { JoinableFactory.RunAsync(async() => { try { await InitializeAsync(); foreach (Lazy <IDependenciesGraphActionHandler, IOrderPrecedenceMetadataView> handler in _graphActionHandlers) { if (handler.Value.TryHandleRequest(context)) { _changeTracker.RegisterGraphContext(context); // Only one handler should succeed return; } } } catch (Exception ex) { context.ReportError(ex); } finally { // OnCompleted must be called to display changes context.OnCompleted(); } }); }
private async Task <bool> RestoreCoreAsync(ProjectRestoreInfo restoreInfo) { // Restore service always does work regardless of whether the value we pass // them to actually contains changes, only nominate if there are any. byte[] hash = RestoreHasher.CalculateHash(restoreInfo); if (_latestHash != null && Enumerable.SequenceEqual(hash, _latestHash)) { return(true); } _latestHash = hash; JoinableTask <bool> joinableTask = JoinableFactory.RunAsync(() => { return(NominateForRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes return(await joinableTask); }
internal async Task OnRestoreInfoChangedAsync(IProjectVersionedValue <PackageRestoreUnconfiguredInput> e) { PackageRestoreUnconfiguredInput update = e.Value; IVsProjectRestoreInfo2? restoreInfo = e.Value.RestoreInfo; // Restore service always does work regardless of whether the value we pass them to actually // contains changes, only nominate if there are any. if (RestoreComparer.RestoreInfos.Equals(_latestValue, restoreInfo)) { return; } // No configurations - likely during project close if (restoreInfo == null) { return; } _latestValue = restoreInfo; JoinableTask joinableTask = JoinableFactory.RunAsync(() => { return(NominateProjectRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes await joinableTask; }
protected async Task ExecuteWithLock(Func <Task> func) { using (JoinableCollection.Join()) { using (await _lock.EnterAsync().ConfigureAwait(false)) { var task = JoinableFactory.RunAsync(func); await task.Task.ConfigureAwait(false); } } }
private JoinableTask ExecuteWithinLockAsync(Func <Task> task) { // We need to request the lock within a joinable task to ensure that if we are blocking the UI // thread (i.e. when CPS is draining critical tasks on the UI thread and is waiting on this task), // and the lock is already held by another task requesting UI thread access, we don't reach a deadlock. return(JoinableFactory.RunAsync(async delegate { using (JoinableCollection.Join()) using (await _gate.DisposableWaitAsync().ConfigureAwait(false)) { await task().ConfigureAwait(false); } })); }
private Task ProjectPropertyChangedAsync(Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> sources) { IVsProjectRestoreInfo projectRestoreInfo = ProjectRestoreInfoBuilder.Build(sources.Item1); if (projectRestoreInfo != null) { _projectVsServices.Project.Services.ProjectAsynchronousTasks .RegisterCriticalAsyncTask(JoinableFactory.RunAsync(() => _solutionRestoreService .NominateProjectAsync(_projectVsServices.Project.FullPath, projectRestoreInfo, CancellationToken.None)), registerFaultHandler: true); } return(Task.CompletedTask); }
private async Task <bool> RestoreCoreAsync(PackageRestoreUnconfiguredInput value) { ProjectRestoreInfo?restoreInfo = value.RestoreInfo; bool success = false; Assumes.NotNull(restoreInfo); try { // Restore service always does work regardless of whether the value we pass // them to actually contains changes, only nominate if there are any. byte[] hash = RestoreHasher.CalculateHash(restoreInfo); if (_latestHash != null && hash.AsSpan().SequenceEqual(_latestHash)) { SaveNominatedConfiguredVersions(value.ConfiguredInputs); return(true); } _latestHash = hash; _restoreStarted = true; JoinableTask <bool> joinableTask = JoinableFactory.RunAsync(() => { return(NominateForRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); SaveNominatedConfiguredVersions(value.ConfiguredInputs); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes success = await joinableTask; lock (SyncObject) { _restoreStarted = false; } HintProjectDependentFile(restoreInfo); } finally { _restoreStarted = false; } return(success); }
private Task ProjectPropertyChangedAsync(Tuple <ImmutableList <IProjectValueVersions>, TIdentityDictionary> sources) { IVsProjectRestoreInfo projectRestoreInfo = ProjectRestoreInfoBuilder.Build(sources.Item1, _projectVsServices.Project); if (projectRestoreInfo != null) { _projectVsServices.Project.Services.ProjectAsynchronousTasks .RegisterCriticalAsyncTask(JoinableFactory.RunAsync(async() => { await _solutionRestoreService .NominateProjectAsync(_projectVsServices.Project.FullPath, projectRestoreInfo, CancellationToken.None) .ConfigureAwait(false); Microsoft.Internal.Performance.CodeMarkers.Instance.CodeMarker(perfPackageRestoreEnd); }), registerFaultHandler: true); } return(Task.CompletedTask); }
private void NominateProject(ImmutableList <IProjectValueVersions> sources) { IVsProjectRestoreInfo projectRestoreInfo = ProjectRestoreInfoBuilder.Build(sources, _projectVsServices.Project); if (projectRestoreInfo != null) { _projectVsServices.Project.Services.ProjectAsynchronousTasks .RegisterAsyncTask(JoinableFactory.RunAsync(async() => { LogProjectRestoreInfo(_projectVsServices.Project.FullPath, projectRestoreInfo); await _solutionRestoreService .NominateProjectAsync(_projectVsServices.Project.FullPath, projectRestoreInfo, _projectVsServices.Project.Services.ProjectAsynchronousTasks.UnloadCancellationToken); CodeMarkers.Instance.CodeMarker(CodeMarkerTimerId.PerfPackageRestoreEnd); CompleteLogProjectRestoreInfo(_projectVsServices.Project.FullPath); }), ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); } }
private async Task RestoreAsync(ProjectRestoreInfo restoreInfo) { // Restore service always does work regardless of whether the value we pass them to actually // contains changes, only nominate if there are any. if (RestoreComparer.RestoreInfos.Equals(_latestValue, restoreInfo)) { return; } _latestValue = restoreInfo; JoinableTask joinableTask = JoinableFactory.RunAsync(() => { return(NominateForRestoreAsync(restoreInfo, _projectAsynchronousTasksService.UnloadCancellationToken)); }); _projectAsynchronousTasksService.RegisterAsyncTask(joinableTask, ProjectCriticalOperation.Build | ProjectCriticalOperation.Unload | ProjectCriticalOperation.Rename, registerFaultHandler: true); // Prevent overlap until Restore completes await joinableTask; }
protected override IDisposable LinkExternalInput(ITargetBlock <IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > targetBlock) { Assumes.Present(_configuredProject.Services.ProjectSubscription); bool attemptedStateRestore = false; // Initial state is empty. We will evolve this reference over time, updating it iteratively // on each new data update. UpToDateCheckImplicitConfiguredInput state = UpToDateCheckImplicitConfiguredInput.CreateEmpty(_configuredProject.ProjectConfiguration); IPropagatorBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > transformBlock = DataflowBlockSlim.CreateTransformBlock <IProjectVersionedValue <UpdateValues>, IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> >(TransformAsync); IProjectValueDataSource <IProjectSubscriptionUpdate> source1 = _configuredProject.Services.ProjectSubscription.JointRuleSource; IProjectValueDataSource <IProjectSubscriptionUpdate> source2 = _configuredProject.Services.ProjectSubscription.SourceItemsRuleSource; IProjectItemSchemaService source3 = _projectItemSchemaService; IProjectValueDataSource <IProjectCatalogSnapshot> source4 = _configuredProject.Services.ProjectSubscription.ProjectCatalogSource; return(new DisposableBag { // Sync-link various sources to our transform block ProjectDataSources.SyncLinkTo( source1.SourceBlock.SyncLinkOptions(DataflowOption.WithRuleNames(ProjectPropertiesSchemas)), source2.SourceBlock.SyncLinkOptions(), source3.SourceBlock.SyncLinkOptions(), source4.SourceBlock.SyncLinkOptions(), target: transformBlock, linkOptions: DataflowOption.PropagateCompletion, CancellationToken.None), // Link the transform block to our target block transformBlock.LinkTo(targetBlock, DataflowOption.PropagateCompletion), JoinUpstreamDataSources(source1, source2, source3, source4) }); async Task <IProjectVersionedValue <UpToDateCheckImplicitConfiguredInput> > TransformAsync(IProjectVersionedValue <UpdateValues> e) { if (!attemptedStateRestore) { attemptedStateRestore = true; if (_persistentState is not null) { // Restoring state requires the UI thread. We must use JTF.RunAsync here to ensure the UI // thread is shared between related work and prevent deadlocks. (int ItemHash, DateTime InputsChangedAtUtc)? restoredState = await JoinableFactory.RunAsync(() => _persistentState.RestoreStateAsync(_configuredProject.UnconfiguredProject.FullPath, _configuredProject.ProjectConfiguration.Dimensions, _projectAsynchronousTasksService.UnloadCancellationToken)); if (restoredState is not null) { state = state.WithRestoredState(restoredState.Value.ItemHash, restoredState.Value.InputsChangedAtUtc); } } } int? priorItemHash = state.ItemHash; DateTime priorLastItemsChangedAtUtc = state.LastItemsChangedAtUtc; state = state.Update( jointRuleUpdate: e.Value.Item1, sourceItemsUpdate: e.Value.Item2, projectItemSchema: e.Value.Item3, projectCatalogSnapshot: e.Value.Item4); if (state.ItemHash is not null && _persistentState is not null && (priorItemHash != state.ItemHash || priorLastItemsChangedAtUtc != state.LastItemsChangedAtUtc)) { await _persistentState.StoreStateAsync(_configuredProject.UnconfiguredProject.FullPath, _configuredProject.ProjectConfiguration.Dimensions, state.ItemHash.Value, state.LastItemsChangedAtUtc, _projectAsynchronousTasksService.UnloadCancellationToken); } return(new ProjectVersionedValue <UpToDateCheckImplicitConfiguredInput>(state, e.DataSourceVersions)); } }