From b2606eacf192ffdd7be79c40d6087b0d3cf71ee5 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Tue, 17 Dec 2024 14:42:56 +1100 Subject: [PATCH] Set AsyncLazy.SuppressRecursiveFactoryDetection to true This avoids the overhead associated with the type's re-entrancy prevention in cases where we the code cannot call itself. See https://github.com/microsoft/vs-threading/pull/1265 for more information. --- .../Build/LanguageServiceErrorListProvider.cs | 5 +- .../PropertyPages/AbstractProjectState.cs | 62 +++++++++---------- .../Build/PublishItemsOutputGroupProvider.cs | 5 +- .../Debug/DebugProfileEnumValuesGenerator.cs | 10 +-- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Build/LanguageServiceErrorListProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Build/LanguageServiceErrorListProvider.cs index 09e911bc85..c8ad691bb5 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Build/LanguageServiceErrorListProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Build/LanguageServiceErrorListProvider.cs @@ -36,7 +36,10 @@ public LanguageServiceErrorListProvider( _isLspPullDiagnosticsEnabled = new AsyncLazy( async () => await projectSystemOptions.IsLspPullDiagnosticsEnabledAsync(CancellationToken.None), - joinableTaskContext.Factory); + joinableTaskContext.Factory) + { + SuppressRecursiveFactoryDetection = true + }; } public void SuspendRefresh() diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/PropertyPages/AbstractProjectState.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/PropertyPages/AbstractProjectState.cs index 6b7db0c3b3..fb29bd75ef 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/PropertyPages/AbstractProjectState.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/PropertyPages/AbstractProjectState.cs @@ -9,8 +9,8 @@ internal abstract class AbstractProjectState : IProjectState { protected readonly UnconfiguredProject Project; - private readonly Dictionary _catalogCache; - private readonly Dictionary<(ProjectConfiguration, string, QueryProjectPropertiesContext), IRule?> _ruleCache; + private readonly Dictionary _catalogCache = []; + private readonly Dictionary<(ProjectConfiguration, string, QueryProjectPropertiesContext), IRule?> _ruleCache = []; private readonly AsyncLazy?> _knownProjectConfigurations; private readonly AsyncLazy _defaultProjectConfiguration; @@ -20,10 +20,34 @@ protected AbstractProjectState(UnconfiguredProject project) Project = project; JoinableTaskFactory joinableTaskFactory = project.Services.ThreadingPolicy.JoinableTaskFactory; - _knownProjectConfigurations = new AsyncLazy?>(CreateKnownConfigurationsAsync, joinableTaskFactory); - _defaultProjectConfiguration = new AsyncLazy(CreateDefaultConfigurationAsync, joinableTaskFactory); - _catalogCache = new Dictionary(); - _ruleCache = new Dictionary<(ProjectConfiguration, string, QueryProjectPropertiesContext), IRule?>(); + _knownProjectConfigurations = new AsyncLazy?>(CreateKnownConfigurationsAsync, joinableTaskFactory) + { + SuppressRecursiveFactoryDetection = true + }; + + _defaultProjectConfiguration = new AsyncLazy(CreateDefaultConfigurationAsync, joinableTaskFactory) + { + SuppressRecursiveFactoryDetection = true + }; + + async Task?> CreateKnownConfigurationsAsync() + { + return Project.Services.ProjectConfigurationsService switch + { + IProjectConfigurationsService configurationsService => await configurationsService.GetKnownProjectConfigurationsAsync(), + _ => null + }; + } + + async Task CreateDefaultConfigurationAsync() + { + return Project.Services.ProjectConfigurationsService switch + { + IProjectConfigurationsService2 configurationsService2 => await configurationsService2.GetSuggestedProjectConfigurationAsync(), + IProjectConfigurationsService configurationsService => configurationsService.SuggestedProjectConfiguration, + _ => null + }; + } } /// @@ -60,32 +84,6 @@ protected AbstractProjectState(UnconfiguredProject project) /// public Task GetSuggestedConfigurationAsync() => _defaultProjectConfiguration.GetValueAsync(); - private async Task CreateDefaultConfigurationAsync() - { - if (Project.Services.ProjectConfigurationsService is IProjectConfigurationsService2 configurationsService2) - { - return await configurationsService2.GetSuggestedProjectConfigurationAsync(); - } - else if (Project.Services.ProjectConfigurationsService is IProjectConfigurationsService configurationsService) - { - return configurationsService.SuggestedProjectConfiguration; - } - else - { - return null; - } - } - - private async Task?> CreateKnownConfigurationsAsync() - { - if (Project.Services.ProjectConfigurationsService is IProjectConfigurationsService configurationsService) - { - return await configurationsService.GetKnownProjectConfigurationsAsync(); - } - - return null; - } - /// /// Retrieves the set of property pages that apply to the project level for the given . diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Build/PublishItemsOutputGroupProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Build/PublishItemsOutputGroupProvider.cs index 864ffad252..9fe632a2f2 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Build/PublishItemsOutputGroupProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Build/PublishItemsOutputGroupProvider.cs @@ -34,7 +34,10 @@ internal PublishItemsOutputGroupProvider( { _outputGroups = new AsyncLazy>( GetOutputGroupMetadataAsync, - projectThreadingService.JoinableTaskFactory); + projectThreadingService.JoinableTaskFactory) + { + SuppressRecursiveFactoryDetection = true + }; async Task> GetOutputGroupMetadataAsync() { diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/DebugProfileEnumValuesGenerator.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/DebugProfileEnumValuesGenerator.cs index df7017b83c..970f66de0f 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/DebugProfileEnumValuesGenerator.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/DebugProfileEnumValuesGenerator.cs @@ -19,21 +19,21 @@ internal DebugProfileEnumValuesGenerator( ILaunchSettingsProvider profileProvider, IProjectThreadingService threadingService) { - Requires.NotNull(profileProvider); - Requires.NotNull(threadingService); - _listedValues = new AsyncLazy>( () => { ILaunchSettings? snapshot = profileProvider.CurrentSnapshot; ICollection values = snapshot is null - ? Array.Empty() + ? [] : GetEnumeratorEnumValues(snapshot); return Task.FromResult(values); }, - threadingService.JoinableTaskFactory); + threadingService.JoinableTaskFactory) + { + SuppressRecursiveFactoryDetection = true + }; } public Task> GetListedValuesAsync()