private async Task ProcessAsync(ProjectToDocumentMap projectToDocumentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessAsync, _cancellationToken)) { // quick exit if (projectToDocumentMap.Count == 0) { return; } // Add a progress item for each (document, symbol, finder) set that we will execute. // We'll mark the item as completed in "ProcessDocumentAsync". var totalFindCount = projectToDocumentMap.Sum( kvp1 => kvp1.Value.Sum(kvp2 => kvp2.Value.Count)); await _progressTracker.AddItemsAsync(totalFindCount).ConfigureAwait(false); using var _ = ArrayBuilder <Task> .GetInstance(out var tasks); foreach (var(project, documentMap) in projectToDocumentMap) { tasks.Add(Task.Factory.StartNew(() => ProcessProjectAsync(project, documentMap), _cancellationToken, TaskCreationOptions.None, _scheduler).Unwrap()); } await Task.WhenAll(tasks).ConfigureAwait(false); } }
private async Task ProcessAsync(ProjectToDocumentMap projectToDocumentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessAsync, _cancellationToken)) { // quick exit if (projectToDocumentMap.Count == 0) { return; } // Get the connected components of the dependency graph and process each individually. // That way once a component is done we can throw away all the memory associated with // it. // For each connected component, we'll process the individual projects from bottom to // top. i.e. we'll first process the projects with no dependencies. Then the projects // that depend on those projects, and so and. This way we always have creates the // dependent compilations when they're needed by later projects. If we went the other // way (i.e. processed the projects with lots of project dependencies first), then we'd // have to create all their depedent compilations in order to get their compilation. // This would be very expensive and would take a lot of time before we got our first // result. var connectedProjects = _dependencyGraph.GetDependencySets(_cancellationToken); // Add a progress item for each (document, symbol, finder) set that we will execute. // We'll mark the item as completed in "ProcessDocumentAsync". var totalFindCount = projectToDocumentMap.Sum( kvp1 => kvp1.Value.Sum(kvp2 => kvp2.Value.Count)); await _progressTracker.AddItemsAsync(totalFindCount).ConfigureAwait(false); // Now, go through each connected project set and process it independently. foreach (var connectedProjectSet in connectedProjects) { _cancellationToken.ThrowIfCancellationRequested(); await ProcessProjectsAsync( connectedProjectSet, projectToDocumentMap).ConfigureAwait(false); } } }