Skip to content

Commit ded603f

Browse files
committed
Experiment with preloading MEF service dependencies asynchronously
1 parent 47215bd commit ded603f

16 files changed

+138
-64
lines changed

src/VisualStudio/Core/Def/Implementation/Diagnostics/DiagnosticProgressReporter.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using System;
4-
using System.ComponentModel.Composition;
4+
using System.Composition;
55
using System.Threading.Tasks;
66
using Microsoft.CodeAnalysis.Diagnostics;
7+
using Microsoft.CodeAnalysis.Host.Mef;
78
using Microsoft.CodeAnalysis.SolutionCrawler;
9+
using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
810
using Microsoft.VisualStudio.Shell;
911
using Microsoft.VisualStudio.TaskStatusCenter;
1012
using Roslyn.Utilities;
1113

1214
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics
1315
{
1416
[Export(typeof(DiagnosticProgressReporter))]
15-
internal sealed class DiagnosticProgressReporter
17+
[PreloadServices(typeof(SVsTaskStatusCenterService))]
18+
[Shared]
19+
internal sealed class DiagnosticProgressReporter : IPreloadService
1620
{
1721
private static readonly TimeSpan s_minimumInterval = TimeSpan.FromMilliseconds(200);
1822

@@ -30,6 +34,7 @@ internal sealed class DiagnosticProgressReporter
3034
private volatile ITaskHandler _taskHandler;
3135

3236
[ImportingConstructor]
37+
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
3338
public DiagnosticProgressReporter(
3439
SVsServiceProvider serviceProvider,
3540
IDiagnosticService diagnosticService,

src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractPackage.cs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,33 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
2727
ForegroundObject = new ForegroundThreadAffinitizedObject(componentModel.GetService<IThreadingContext>());
2828
}
2929

30-
protected void LoadComponentsInUIContextOnceSolutionFullyLoaded(CancellationToken cancellationToken)
30+
protected async Task LoadComponentsInUIContextOnceSolutionFullyLoadedAsync(CancellationToken cancellationToken)
3131
{
32-
ThreadHelper.ThrowIfNotOnUIThread();
32+
await KnownUIContexts.SolutionExistsAndFullyLoadedContext;
33+
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
3334

34-
if (KnownUIContexts.SolutionExistsAndFullyLoadedContext.IsActive)
35-
{
36-
// if we are already in the right UI context, load it right away
37-
LoadComponentsInUIContext(cancellationToken);
38-
}
39-
else
35+
var componentModel = (IComponentModel)await GetServiceAsync(typeof(SComponentModel));
36+
Assumes.Present(componentModel);
37+
38+
// Make sure the service dependencies are loaded, then preload services that require construction on the
39+
// main thread.
40+
var preloadServices = componentModel.DefaultExportProvider.GetExports<IPreloadService, PreloadServiceMetadata>();
41+
foreach (var preloadService in preloadServices)
4042
{
41-
// load them when it is a right context.
42-
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged += OnSolutionExistsAndFullyLoadedContext;
43+
foreach (var serviceType in preloadService.Metadata.PreloadedServices)
44+
{
45+
await GetServiceAsync(serviceType);
46+
}
4347
}
44-
}
45-
46-
private void OnSolutionExistsAndFullyLoadedContext(object sender, UIContextChangedEventArgs e)
47-
{
48-
ThreadHelper.ThrowIfNotOnUIThread();
4948

50-
if (e.Activated)
49+
foreach (var preloadService in preloadServices)
5150
{
52-
// unsubscribe from it
53-
KnownUIContexts.SolutionExistsAndFullyLoadedContext.UIContextChanged -= OnSolutionExistsAndFullyLoadedContext;
54-
55-
// load components
56-
LoadComponentsInUIContext(CancellationToken.None);
51+
_ = preloadService.Value;
5752
}
53+
54+
await LoadComponentsAsync(cancellationToken);
5855
}
5956

60-
protected abstract void LoadComponentsInUIContext(CancellationToken cancellationToken);
57+
protected abstract Task LoadComponentsAsync(CancellationToken cancellationToken);
6158
}
6259
}

src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractPackage`2.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
9595
Workspace.AdviseSolutionEvents(solution);
9696
}
9797

98-
LoadComponentsInUIContextOnceSolutionFullyLoaded(cancellationToken);
98+
_ = LoadComponentsInUIContextOnceSolutionFullyLoadedAsync(cancellationToken);
9999
}
100100

101-
protected override void LoadComponentsInUIContext(CancellationToken cancellationToken)
101+
protected override async Task LoadComponentsAsync(CancellationToken cancellationToken)
102102
{
103-
ForegroundObject.AssertIsForeground();
103+
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
104104

105105
// Ensure the nuget package services are initialized after we've loaded
106106
// the solution.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
4+
{
5+
internal interface IPreloadService
6+
{
7+
}
8+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Collections.Immutable;
6+
using Roslyn.Utilities;
7+
8+
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
9+
{
10+
internal class PreloadServiceMetadata
11+
{
12+
public PreloadServiceMetadata(IDictionary<string, object> data)
13+
{
14+
PreloadedServices = ImmutableArray.CreateRange((IEnumerable<Type>)data.GetValueOrDefault(nameof(PreloadServicesAttribute.PreloadedServiceTypes)));
15+
}
16+
17+
public ImmutableArray<Type> PreloadedServices
18+
{
19+
get;
20+
}
21+
}
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System;
4+
using System.Composition;
5+
6+
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
7+
{
8+
[MetadataAttribute]
9+
[AttributeUsage(AttributeTargets.Class)]
10+
internal sealed class PreloadServicesAttribute : ExportAttribute
11+
{
12+
public PreloadServicesAttribute(params Type[] preloadedServiceTypes)
13+
: base(typeof(IPreloadService))
14+
{
15+
PreloadedServiceTypes = preloadedServiceTypes ?? Type.EmptyTypes;
16+
}
17+
18+
public Type[] PreloadedServiceTypes
19+
{
20+
get;
21+
}
22+
}
23+
}

src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Collections.Immutable;
6-
using System.ComponentModel.Composition;
6+
using System.Composition;
77
using System.IO;
88
using System.Linq;
99
using Microsoft.CodeAnalysis;
@@ -14,6 +14,7 @@
1414
using Microsoft.CodeAnalysis.Scripting;
1515
using Microsoft.CodeAnalysis.Text;
1616
using Microsoft.VisualStudio.Editor;
17+
using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
1718
using Microsoft.VisualStudio.Shell;
1819
using Microsoft.VisualStudio.Shell.Interop;
1920
using Microsoft.VisualStudio.Text;
@@ -25,7 +26,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
2526
using Workspace = Microsoft.CodeAnalysis.Workspace;
2627

2728
[Export(typeof(MiscellaneousFilesWorkspace))]
28-
internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IVsRunningDocTableEvents2
29+
[PreloadServices(typeof(SVsRunningDocumentTable), typeof(SVsTextManager))]
30+
[Shared]
31+
internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IVsRunningDocTableEvents2, IPreloadService
2932
{
3033
private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService;
3134
private readonly IMetadataAsSourceFileService _fileTrackingMetadataAsSourceService;

src/VisualStudio/Core/Def/Implementation/ProjectSystem/RuleSets/RuleSetEventHandler.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
using System;
44
using System.Collections.Generic;
5-
using System.ComponentModel.Composition;
5+
using System.Composition;
66
using System.IO;
7-
using System.Linq;
8-
using System.Text;
9-
using System.Threading.Tasks;
7+
using Microsoft.CodeAnalysis.Host.Mef;
8+
using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
109
using Microsoft.VisualStudio.Shell;
1110
using Microsoft.VisualStudio.Shell.Interop;
1211
using Roslyn.Utilities;
@@ -15,15 +14,17 @@
1514
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.RuleSets
1615
{
1716
[Export(typeof(RuleSetEventHandler))]
18-
internal sealed class RuleSetEventHandler : IVsTrackProjectDocumentsEvents2, IVsTrackProjectDocumentsEvents3, IVsTrackProjectDocumentsEvents4
17+
[PreloadServices(typeof(SVsTrackProjectDocuments))]
18+
[Shared]
19+
internal sealed class RuleSetEventHandler : IVsTrackProjectDocumentsEvents2, IVsTrackProjectDocumentsEvents3, IVsTrackProjectDocumentsEvents4, IPreloadService
1920
{
2021
private readonly IServiceProvider _serviceProvider;
2122
private bool _eventsHookedUp = false;
2223
private uint _cookie = 0;
2324

2425
[ImportingConstructor]
25-
public RuleSetEventHandler(
26-
[Import(typeof(SVsServiceProvider))]IServiceProvider serviceProvider)
26+
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
27+
public RuleSetEventHandler(SVsServiceProvider serviceProvider)
2728
{
2829
_serviceProvider = serviceProvider;
2930
}

src/VisualStudio/Core/Def/Implementation/TableDataSource/Suppression/VisualStudioDiagnosticListTableCommandHandler.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using System;
4-
using System.ComponentModel.Composition;
4+
using System.Composition;
55
using System.ComponentModel.Design;
66
using Microsoft.VisualStudio.LanguageServices.Implementation.Suppression;
77
using Microsoft.VisualStudio.Shell;
8+
using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
9+
using Microsoft.CodeAnalysis.Host.Mef;
810

911
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource
1012
{
1113
[Export(typeof(VisualStudioDiagnosticListTableCommandHandler))]
12-
internal partial class VisualStudioDiagnosticListTableCommandHandler
14+
[PreloadServices]
15+
[Shared]
16+
internal partial class VisualStudioDiagnosticListTableCommandHandler : IPreloadService
1317
{
1418
private readonly VisualStudioSuppressionFixService _suppressionFixService;
1519
private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService;
1620

1721
[ImportingConstructor]
22+
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
1823
public VisualStudioDiagnosticListTableCommandHandler(
1924
IVisualStudioSuppressionFixService suppressionFixService,
2025
IVisualStudioDiagnosticListSuppressionStateService suppressionStateService)

src/VisualStudio/Core/Def/Implementation/TableDataSource/VisualStudioDiagnosticListTable.BuildTableDataSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource
1515
{
1616
using Workspace = Microsoft.CodeAnalysis.Workspace;
1717

18-
internal partial class VisualStudioDiagnosticListTable : VisualStudioBaseDiagnosticListTable
18+
internal partial class VisualStudioDiagnosticListTable
1919
{
2020
private class BuildTableDataSource : AbstractTableDataSource<DiagnosticData>
2121
{

0 commit comments

Comments
 (0)