Skip to content

Commit c0b81f7

Browse files
committed
Convert to use AsyncLazy so that concurrent requests don't double-execute
It seems likely that we would get multiple requests to the up-to-date check as we're called per-project, and many projects can build in parallel. Better to only do this work once.
1 parent f804cd6 commit c0b81f7

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/UpToDateCheckHost.cs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ internal sealed class UpToDateCheckHost : IUpToDateCheckHost
1212
{
1313
private readonly IVsService<IVsAppId> _vsAppId;
1414
private readonly IVsService<IVsAppCommandLine> _vsAppCommandLine;
15-
private readonly JoinableTaskContext _joinableTaskContext;
1615

17-
private bool? _hasDesignTimeBuild;
16+
private readonly AsyncLazy<bool> _hasDesignTimeBuild;
17+
private readonly CancellationTokenSource _cancellationTokenSource = new();
1818

1919
[ImportingConstructor]
2020
public UpToDateCheckHost(
@@ -24,45 +24,48 @@ public UpToDateCheckHost(
2424
{
2525
_vsAppId = vsAppId;
2626
_vsAppCommandLine = vsAppCommandLine;
27-
_joinableTaskContext = joinableTaskContext;
27+
28+
_hasDesignTimeBuild = new(HasDesignTimeBuildsInternalAsync, joinableTaskContext.Factory);
2829
}
2930

3031
public async ValueTask<bool> HasDesignTimeBuildsAsync(CancellationToken cancellationToken)
3132
{
32-
_hasDesignTimeBuild ??= await HasDesignTimeBuildsInternalAsync();
33+
cancellationToken.Register(_cancellationTokenSource.Cancel);
3334

34-
return _hasDesignTimeBuild.Value;
35+
return await _hasDesignTimeBuild.GetValueAsync(cancellationToken);
36+
}
3537

36-
async Task<bool> HasDesignTimeBuildsInternalAsync()
37-
{
38-
IVsAppCommandLine vsAppCommandLine = await _vsAppCommandLine.GetValueAsync(cancellationToken);
38+
private async Task<bool> HasDesignTimeBuildsInternalAsync()
39+
{
40+
CancellationToken token = _cancellationTokenSource.Token;
41+
42+
IVsAppCommandLine vsAppCommandLine = await _vsAppCommandLine.GetValueAsync(token);
3943

40-
if (ErrorHandler.Succeeded(vsAppCommandLine.GetOption("populateSolutionCache", out int populateSolutionCachePresent, out string _)))
44+
if (ErrorHandler.Succeeded(vsAppCommandLine.GetOption("populateSolutionCache", out int populateSolutionCachePresent, out string _)))
45+
{
46+
if (populateSolutionCachePresent != 0)
4147
{
42-
if (populateSolutionCachePresent != 0)
43-
{
44-
// Design time builds are available when running with /populateSolutionCache.
45-
return true;
46-
}
48+
// Design time builds are available when running with /populateSolutionCache.
49+
return true;
4750
}
51+
}
4852

49-
IVsAppId vsAppId = await _vsAppId.GetValueAsync(cancellationToken);
53+
IVsAppId vsAppId = await _vsAppId.GetValueAsync(token);
5054

51-
if (ErrorHandler.Succeeded(vsAppId.GetProperty((int)__VSAPROPID10.VSAPROPID_IsInCommandLineMode, out object value)))
55+
if (ErrorHandler.Succeeded(vsAppId.GetProperty((int)__VSAPROPID10.VSAPROPID_IsInCommandLineMode, out object value)))
56+
{
57+
if (value is bool isInCommandLineMode)
5258
{
53-
if (value is bool isInCommandLineMode)
54-
{
55-
// Design-time builds do not occur in command line mode, other than with /populateSolutionCache (checked earlier).
56-
return !isInCommandLineMode;
57-
}
59+
// Design-time builds do not occur in command line mode, other than with /populateSolutionCache (checked earlier).
60+
return !isInCommandLineMode;
5861
}
62+
}
5963

60-
// We shouldn't reach this point.
61-
System.Diagnostics.Debug.Fail($"{nameof(UpToDateCheckHost)}.{nameof(HasDesignTimeBuildsAsync)} was unable to determine result reliably.");
64+
// We shouldn't reach this point.
65+
System.Diagnostics.Debug.Fail($"{nameof(UpToDateCheckHost)}.{nameof(HasDesignTimeBuildsAsync)} was unable to determine result reliably.");
6266

63-
// Assume we don't have design-time builds, to prevent hangs from waiting for snapshot data that will never arrive.
64-
return false;
65-
}
67+
// Assume we don't have design-time builds, to prevent hangs from waiting for snapshot data that will never arrive.
68+
return false;
6669
}
6770
}
6871
}

0 commit comments

Comments
 (0)