Skip to content

Commit af377ce

Browse files
authored
Merge pull request #271 from tonyhallett/mef-threading
make the MEF parts free-threaded
2 parents e9dea99 + 0a9165d commit af377ce

File tree

7 files changed

+45
-23
lines changed

7 files changed

+45
-23
lines changed

FineCodeCoverageTests/FineCodeCoverageTests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
<Deterministic>true</Deterministic>
1717
<NuGetPackageImportStamp>
1818
</NuGetPackageImportStamp>
19+
<RunSettingsFilePath>
20+
</RunSettingsFilePath>
1921
</PropertyGroup>
2022
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
2123
<DebugSymbols>true</DebugSymbols>

SharedProject/Core/Model/CoverageProjectFactory.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
using System;
22
using System.ComponentModel.Composition;
3-
using System.Threading;
3+
using System.Threading.Tasks;
44
using EnvDTE;
55
using EnvDTE80;
66
using FineCodeCoverage.Engine.FileSynchronization;
77
using FineCodeCoverage.Options;
88
using Microsoft.Build.Locator;
99
using Microsoft.VisualStudio.Shell;
10+
using Microsoft.VisualStudio.Threading;
1011

1112
namespace FineCodeCoverage.Engine.Model
1213
{
@@ -17,8 +18,8 @@ internal class CoverageProjectFactory : ICoverageProjectFactory
1718
private readonly IFileSynchronizationUtil fileSynchronizationUtil;
1819
private readonly ILogger logger;
1920
private readonly ICoverageProjectSettingsManager coverageProjectSettingsManager;
20-
private readonly DTE2 dte;
2121
private bool canUseMsBuildWorkspace = true;
22+
private readonly AsyncLazy<DTE2> lazyDTE2;
2223

2324
[ImportingConstructor]
2425
public CoverageProjectFactory(
@@ -33,8 +34,12 @@ public CoverageProjectFactory(
3334
this.fileSynchronizationUtil = fileSynchronizationUtil;
3435
this.logger = logger;
3536
this.coverageProjectSettingsManager = coverageProjectSettingsManager;
36-
ThreadHelper.ThrowIfNotOnUIThread();
37-
dte = (DTE2)serviceProvider.GetService(typeof(DTE));
37+
38+
lazyDTE2 = new AsyncLazy<DTE2>(async () =>
39+
{
40+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
41+
return (DTE2)serviceProvider.GetService(typeof(DTE));
42+
},ThreadHelper.JoinableTaskFactory);
3843
}
3944

4045
public void Initialize()
@@ -48,13 +53,15 @@ public void Initialize()
4853
canUseMsBuildWorkspace = false;
4954
}
5055
}
51-
public ICoverageProject Create()
56+
public async Task<ICoverageProject> CreateAsync()
5257
{
53-
return new CoverageProject(
58+
var dte2 = await lazyDTE2.GetValueAsync();
59+
60+
return new CoverageProject(
5461
appOptionsProvider,
5562
fileSynchronizationUtil,
5663
logger,
57-
dte,
64+
dte2,
5865
coverageProjectSettingsManager,
5966
canUseMsBuildWorkspace);
6067
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
namespace FineCodeCoverage.Engine.Model
1+
using System.Threading.Tasks;
2+
3+
namespace FineCodeCoverage.Engine.Model
24
{
35
internal interface ICoverageProjectFactory
46
{
5-
ICoverageProject Create();
7+
Task<ICoverageProject> CreateAsync();
68
void Initialize();
79
}
810
}

SharedProject/Core/SourceFileOpener.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
using EnvDTE;
55
using EnvDTE80;
66
using FineCodeCoverage.Engine.Cobertura;
7-
using Microsoft;
87
using Microsoft.VisualStudio.Shell;
8+
using Microsoft.VisualStudio.Threading;
99

1010
namespace FineCodeCoverage.Engine
1111
{
@@ -15,7 +15,7 @@ internal class SourceFileOpener : ISourceFileOpener
1515
private readonly ICoberturaUtil coberturaUtil;
1616
private readonly IMessageBox messageBox;
1717
private readonly ILogger logger;
18-
private readonly DTE2 dte;
18+
private readonly AsyncLazy<DTE2> lazyDTE2;
1919

2020
[ImportingConstructor]
2121
public SourceFileOpener(
@@ -27,9 +27,11 @@ public SourceFileOpener(
2727
this.coberturaUtil = coberturaUtil;
2828
this.messageBox = messageBox;
2929
this.logger = logger;
30-
ThreadHelper.ThrowIfNotOnUIThread();
31-
dte = (DTE2)serviceProvider.GetService(typeof(DTE));
32-
Assumes.Present(dte);
30+
lazyDTE2 = new AsyncLazy<DTE2>(async () =>
31+
{
32+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
33+
return (DTE2)serviceProvider.GetService(typeof(DTE));
34+
}, ThreadHelper.JoinableTaskFactory);
3335
}
3436
public async System.Threading.Tasks.Task OpenFileAsync(string assemblyName, string qualifiedClassName, int file, int line)
3537
{
@@ -46,6 +48,7 @@ public async System.Threading.Tasks.Task OpenFileAsync(string assemblyName, stri
4648
}
4749

4850
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
51+
var dte = await lazyDTE2.GetValueAsync();
4952
dte.MainWindow.Activate();
5053

5154
foreach (var sourceFile in sourceFiles)

SharedProject/Core/Utilities/SolutionEvents.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ public SolutionEvents(
1919
IServiceProvider serviceProvider
2020
)
2121
{
22-
ThreadHelper.ThrowIfNotOnUIThread();
23-
var vsSolution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
24-
Assumes.Present(vsSolution);
25-
vsSolution.AdviseSolutionEvents(this, out uint _);
22+
ThreadHelper.JoinableTaskFactory.Run(async () =>
23+
{
24+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
25+
var vsSolution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution));
26+
Assumes.Present(vsSolution);
27+
vsSolution.AdviseSolutionEvents(this, out uint _);
28+
});
2629
}
2730

2831
public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded)

SharedProject/Impl/CoverageColour/Provider/CoverageColorProvider.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.VisualStudio;
66
using Microsoft.VisualStudio.Shell;
77
using Microsoft.VisualStudio.Shell.Interop;
8+
using Microsoft.VisualStudio.Threading;
89
using Task = System.Threading.Tasks.Task;
910

1011
namespace FineCodeCoverage.Impl
@@ -13,13 +14,13 @@ namespace FineCodeCoverage.Impl
1314
[Export(typeof(ICoverageColours))]
1415
internal class CoverageColorProvider : ICoverageColoursProvider, ICoverageColours
1516
{
16-
private readonly IVsFontAndColorStorage fontAndColorStorage;
1717
private readonly ILogger logger;
1818
private readonly uint storeFlags = (uint)(__FCSTORAGEFLAGS.FCSF_READONLY | __FCSTORAGEFLAGS.FCSF_LOADDEFAULTS | __FCSTORAGEFLAGS.FCSF_NOAUTOCOLORS | __FCSTORAGEFLAGS.FCSF_PROPAGATECHANGES);
1919
private readonly System.Windows.Media.Color defaultCoverageTouchedArea = System.Windows.Media.Colors.Green;
2020
private readonly System.Windows.Media.Color defaultCoverageNotTouchedArea = System.Windows.Media.Colors.Red;
2121
private readonly System.Windows.Media.Color defaultCoveragePartiallyTouchedArea = System.Windows.Media.Color.FromRgb(255, 165, 0);
2222
private Guid categoryWithCoverage = Guid.Parse("ff349800-ea43-46c1-8c98-878e78f46501");
23+
private AsyncLazy<IVsFontAndColorStorage> lazyIVsFontAndColorStorage;
2324
private bool coverageColoursFromFontsAndColours;
2425
private bool canUseFontsAndColours = true;
2526
public System.Windows.Media.Color CoverageTouchedArea { get; set; }
@@ -37,9 +38,12 @@ public CoverageColorProvider(
3738
ILogger logger
3839
)
3940
{
40-
ThreadHelper.ThrowIfNotOnUIThread();
41-
fontAndColorStorage = (IVsFontAndColorStorage)serviceProvider.GetService(typeof(IVsFontAndColorStorage));
42-
Assumes.Present(fontAndColorStorage);
41+
lazyIVsFontAndColorStorage = new AsyncLazy<IVsFontAndColorStorage>(async () =>
42+
{
43+
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
44+
return (IVsFontAndColorStorage)serviceProvider.GetService(typeof(IVsFontAndColorStorage));
45+
}, ThreadHelper.JoinableTaskFactory);
46+
4347
coverageColoursFromFontsAndColours = appOptionsProvider.Get().CoverageColoursFromFontsAndColours;
4448
appOptionsProvider.OptionsChanged += AppOptionsProvider_OptionsChanged;
4549
this.logger = logger;
@@ -81,6 +85,7 @@ public async Task PrepareAsync()
8185

8286
private async Task UpdateColoursFromFontsAndColorsAsync()
8387
{
88+
var fontAndColorStorage = await lazyIVsFontAndColorStorage.GetValueAsync();
8489
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
8590
var success = fontAndColorStorage.OpenCategory(ref categoryWithCoverage, storeFlags);
8691
var usedFontsAndColors = false;

SharedProject/Impl/TestContainerDiscovery/TestOperation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ private async Task<List<ICoverageProject>> GetCoverageProjectsAsync(TestConfigur
3434
List<ICoverageProject> coverageProjects = new List<ICoverageProject>();
3535
foreach (var container in testContainers)
3636
{
37-
var project = coverageProjectFactory.Create();
37+
var project = await coverageProjectFactory.CreateAsync();
3838
coverageProjects.Add(project);
3939
project.ProjectName = container.ProjectName;
4040
project.TestDllFile = container.Source;

0 commit comments

Comments
 (0)