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);
            }
        }
Esempio n. 2
0
        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);
                }
            }
        }