コード例 #1
0
        public void PostCacheRequest(CacheRequest cacheRequest)
        {
            Task.Run(async() =>
            {
                try
                {
                    (CacheResult cacheResult, int projectContextId) = await ProcessCacheRequest(cacheRequest);
                    _buildManager.PostCacheResult(cacheRequest, cacheResult, projectContextId);
                }
                catch (Exception e)
                {
                    _buildManager.PostCacheResult(cacheRequest, CacheResult.IndicateException(e), BuildEventContext.InvalidProjectContextId);
                }
            }, _cancellationToken);

            async Task <(CacheResult Result, int ProjectContextId)> ProcessCacheRequest(CacheRequest request)
            {
                // Prevent needless evaluation if design time builds detected.
                if (_projectCacheDescriptor.VsWorkaround && DesignTimeBuildsDetected)
                {
                    // The BuildManager should disable the cache when it finds its servicing design time builds.
                    return(CacheResult.IndicateNonCacheHit(CacheResultType.CacheMiss), BuildEventContext.InvalidProjectContextId);
                }

                EvaluateProjectIfNecessary(request);

                // Detect design time builds.
                if (_projectCacheDescriptor.VsWorkaround)
                {
                    var isDesignTimeBuild = IsDesignTimeBuild(request.Configuration.Project);

                    var previousValue = Interlocked.CompareExchange(
                        ref DesignTimeBuildsDetected,
                        new NullableBool(isDesignTimeBuild),
                        null);

                    ErrorUtilities.VerifyThrowInternalError(
                        previousValue is null || previousValue == false || isDesignTimeBuild,
                        "Either all builds in a build session or design time builds, or none");

                    // No point progressing with expensive plugin initialization or cache query if design time build detected.
                    if (DesignTimeBuildsDetected)
                    {
                        // The BuildManager should disable the cache when it finds its servicing design time builds.
                        return(CacheResult.IndicateNonCacheHit(CacheResultType.CacheMiss), BuildEventContext.InvalidProjectContextId);
                    }
                }

                // TODO: remove after we change VS to set the cache descriptor via build parameters.
                // VS workaround needs to wait until the first project is evaluated to extract enough information to initialize the plugin.
                // No cache request can progress until late initialization is complete.
                if (_projectCacheDescriptor.VsWorkaround)
                {
                    if (Interlocked.CompareExchange(
                            ref LateInitializationForVSWorkaroundCompleted,
                            new TaskCompletionSource <bool>(),
                            null) is null)
                    {
                        await LateInitializePluginForVsWorkaround(request);

                        LateInitializationForVSWorkaroundCompleted.SetResult(true);
                    }
                    else
                    {
                        // Can't be null. If the thread got here it means another thread initialized the completion source.
                        await LateInitializationForVSWorkaroundCompleted !.Task;
                    }
                }

                ErrorUtilities.VerifyThrowInternalError(
                    LateInitializationForVSWorkaroundCompleted is null ||
                    (_projectCacheDescriptor.VsWorkaround && LateInitializationForVSWorkaroundCompleted.Task.IsCompleted),
                    "Completion source should be null when this is not the VS workaround");

                BuildRequestData buildRequest = new BuildRequestData(
                    cacheRequest.Configuration.Project,
                    cacheRequest.Submission.BuildRequestData.TargetNames.ToArray());
                BuildEventContext buildEventContext = _loggingService.CreateProjectCacheBuildEventContext(
                    cacheRequest.Submission.SubmissionId,
                    evaluationId: cacheRequest.Configuration.Project.EvaluationId,
                    projectInstanceId: cacheRequest.Configuration.ConfigurationId,
                    projectFile: cacheRequest.Configuration.Project.FullPath);

                CacheResult cacheResult;

                try
                {
                    cacheResult = await GetCacheResultAsync(buildRequest, cacheRequest.Configuration, buildEventContext);
                }
                catch (Exception ex)
                {
                    // Wrap the exception here so we can preserve the ProjectContextId
                    cacheResult = CacheResult.IndicateException(ex);
                }

                return(cacheResult, buildEventContext.ProjectContextId);
            }